sidekiq 5.2.6 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq might be problematic. Click here for more details.

Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +537 -8
  3. data/LICENSE.txt +9 -0
  4. data/README.md +47 -50
  5. data/bin/sidekiq +22 -3
  6. data/bin/sidekiqload +213 -115
  7. data/bin/sidekiqmon +11 -0
  8. data/lib/generators/sidekiq/job_generator.rb +57 -0
  9. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  10. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  11. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  12. data/lib/sidekiq/api.rb +556 -351
  13. data/lib/sidekiq/capsule.rb +127 -0
  14. data/lib/sidekiq/cli.rb +203 -226
  15. data/lib/sidekiq/client.rb +121 -101
  16. data/lib/sidekiq/component.rb +68 -0
  17. data/lib/sidekiq/config.rb +274 -0
  18. data/lib/sidekiq/deploy.rb +62 -0
  19. data/lib/sidekiq/embedded.rb +61 -0
  20. data/lib/sidekiq/fetch.rb +49 -42
  21. data/lib/sidekiq/job.rb +374 -0
  22. data/lib/sidekiq/job_logger.rb +33 -7
  23. data/lib/sidekiq/job_retry.rb +131 -108
  24. data/lib/sidekiq/job_util.rb +105 -0
  25. data/lib/sidekiq/launcher.rb +203 -105
  26. data/lib/sidekiq/logger.rb +131 -0
  27. data/lib/sidekiq/manager.rb +43 -46
  28. data/lib/sidekiq/metrics/query.rb +153 -0
  29. data/lib/sidekiq/metrics/shared.rb +95 -0
  30. data/lib/sidekiq/metrics/tracking.rb +136 -0
  31. data/lib/sidekiq/middleware/chain.rb +113 -56
  32. data/lib/sidekiq/middleware/current_attributes.rb +56 -0
  33. data/lib/sidekiq/middleware/i18n.rb +7 -7
  34. data/lib/sidekiq/middleware/modules.rb +21 -0
  35. data/lib/sidekiq/monitor.rb +146 -0
  36. data/lib/sidekiq/paginator.rb +28 -16
  37. data/lib/sidekiq/processor.rb +108 -107
  38. data/lib/sidekiq/rails.rb +49 -38
  39. data/lib/sidekiq/redis_client_adapter.rb +96 -0
  40. data/lib/sidekiq/redis_connection.rb +38 -107
  41. data/lib/sidekiq/ring_buffer.rb +29 -0
  42. data/lib/sidekiq/scheduled.rb +111 -49
  43. data/lib/sidekiq/sd_notify.rb +149 -0
  44. data/lib/sidekiq/systemd.rb +24 -0
  45. data/lib/sidekiq/testing/inline.rb +6 -5
  46. data/lib/sidekiq/testing.rb +66 -84
  47. data/lib/sidekiq/transaction_aware_client.rb +44 -0
  48. data/lib/sidekiq/version.rb +3 -1
  49. data/lib/sidekiq/web/action.rb +15 -11
  50. data/lib/sidekiq/web/application.rb +123 -79
  51. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  52. data/lib/sidekiq/web/helpers.rb +137 -106
  53. data/lib/sidekiq/web/router.rb +23 -19
  54. data/lib/sidekiq/web.rb +56 -107
  55. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  56. data/lib/sidekiq.rb +92 -182
  57. data/sidekiq.gemspec +25 -16
  58. data/web/assets/images/apple-touch-icon.png +0 -0
  59. data/web/assets/javascripts/application.js +130 -61
  60. data/web/assets/javascripts/base-charts.js +106 -0
  61. data/web/assets/javascripts/chart.min.js +13 -0
  62. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  63. data/web/assets/javascripts/dashboard-charts.js +166 -0
  64. data/web/assets/javascripts/dashboard.js +36 -292
  65. data/web/assets/javascripts/metrics.js +264 -0
  66. data/web/assets/stylesheets/application-dark.css +147 -0
  67. data/web/assets/stylesheets/application-rtl.css +2 -95
  68. data/web/assets/stylesheets/application.css +102 -522
  69. data/web/locales/ar.yml +71 -65
  70. data/web/locales/cs.yml +62 -62
  71. data/web/locales/da.yml +60 -53
  72. data/web/locales/de.yml +65 -53
  73. data/web/locales/el.yml +43 -24
  74. data/web/locales/en.yml +84 -66
  75. data/web/locales/es.yml +70 -54
  76. data/web/locales/fa.yml +65 -65
  77. data/web/locales/fr.yml +83 -62
  78. data/web/locales/gd.yml +99 -0
  79. data/web/locales/he.yml +65 -64
  80. data/web/locales/hi.yml +59 -59
  81. data/web/locales/it.yml +53 -53
  82. data/web/locales/ja.yml +75 -64
  83. data/web/locales/ko.yml +52 -52
  84. data/web/locales/lt.yml +83 -0
  85. data/web/locales/nb.yml +61 -61
  86. data/web/locales/nl.yml +52 -52
  87. data/web/locales/pl.yml +45 -45
  88. data/web/locales/pt-br.yml +63 -55
  89. data/web/locales/pt.yml +51 -51
  90. data/web/locales/ru.yml +68 -63
  91. data/web/locales/sv.yml +53 -53
  92. data/web/locales/ta.yml +60 -60
  93. data/web/locales/uk.yml +62 -61
  94. data/web/locales/ur.yml +64 -64
  95. data/web/locales/vi.yml +83 -0
  96. data/web/locales/zh-cn.yml +43 -16
  97. data/web/locales/zh-tw.yml +42 -8
  98. data/web/views/_footer.erb +6 -3
  99. data/web/views/_job_info.erb +21 -4
  100. data/web/views/_metrics_period_select.erb +12 -0
  101. data/web/views/_nav.erb +1 -1
  102. data/web/views/_paging.erb +2 -0
  103. data/web/views/_poll_link.erb +3 -6
  104. data/web/views/_summary.erb +7 -7
  105. data/web/views/busy.erb +75 -25
  106. data/web/views/dashboard.erb +58 -18
  107. data/web/views/dead.erb +3 -3
  108. data/web/views/layout.erb +3 -1
  109. data/web/views/metrics.erb +82 -0
  110. data/web/views/metrics_for_job.erb +68 -0
  111. data/web/views/morgue.erb +14 -15
  112. data/web/views/queue.erb +33 -24
  113. data/web/views/queues.erb +13 -3
  114. data/web/views/retries.erb +16 -17
  115. data/web/views/retry.erb +3 -3
  116. data/web/views/scheduled.erb +17 -15
  117. metadata +69 -69
  118. data/.github/contributing.md +0 -32
  119. data/.github/issue_template.md +0 -11
  120. data/.gitignore +0 -15
  121. data/.travis.yml +0 -11
  122. data/3.0-Upgrade.md +0 -70
  123. data/4.0-Upgrade.md +0 -53
  124. data/5.0-Upgrade.md +0 -56
  125. data/COMM-LICENSE +0 -97
  126. data/Ent-Changes.md +0 -238
  127. data/Gemfile +0 -23
  128. data/LICENSE +0 -9
  129. data/Pro-2.0-Upgrade.md +0 -138
  130. data/Pro-3.0-Upgrade.md +0 -44
  131. data/Pro-4.0-Upgrade.md +0 -35
  132. data/Pro-Changes.md +0 -759
  133. data/Rakefile +0 -9
  134. data/bin/sidekiqctl +0 -20
  135. data/code_of_conduct.md +0 -50
  136. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  137. data/lib/sidekiq/core_ext.rb +0 -1
  138. data/lib/sidekiq/ctl.rb +0 -221
  139. data/lib/sidekiq/delay.rb +0 -42
  140. data/lib/sidekiq/exception_handler.rb +0 -29
  141. data/lib/sidekiq/extensions/action_mailer.rb +0 -57
  142. data/lib/sidekiq/extensions/active_record.rb +0 -40
  143. data/lib/sidekiq/extensions/class_methods.rb +0 -40
  144. data/lib/sidekiq/extensions/generic_proxy.rb +0 -31
  145. data/lib/sidekiq/logging.rb +0 -122
  146. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
  147. data/lib/sidekiq/util.rb +0 -66
  148. data/lib/sidekiq/worker.rb +0 -220
@@ -1,39 +1,39 @@
1
1
  <ul class="list-unstyled summary row">
2
2
  <li class="processed col-sm-1">
3
- <span class="count"><%= number_with_delimiter(stats.processed) %></span>
3
+ <span id="txtProcessed" class="count"><%= number_with_delimiter(stats.processed) %></span>
4
4
  <span class="desc"><%= t('Processed') %></span>
5
5
  </li>
6
6
  <li class="failed col-sm-1">
7
- <span class="count"><%= number_with_delimiter(stats.failed) %></span>
7
+ <span id="txtFailed" class="count"><%= number_with_delimiter(stats.failed) %></span>
8
8
  <span class="desc"><%= t('Failed') %></span>
9
9
  </li>
10
10
  <li class="busy col-sm-1">
11
11
  <a href="<%= root_path %>busy">
12
- <span class="count"><%= number_with_delimiter(workers.size) %></span>
12
+ <span id="txtBusy" class="count"><%= number_with_delimiter(workset.size) %></span>
13
13
  <span class="desc"><%= t('Busy') %></span>
14
14
  </a>
15
15
  </li>
16
16
  <li class="enqueued col-sm-1">
17
17
  <a href="<%= root_path %>queues">
18
- <span class="count"><%= number_with_delimiter(stats.enqueued) %></span>
18
+ <span id="txtEnqueued" class="count"><%= number_with_delimiter(stats.enqueued) %></span>
19
19
  <span class="desc"><%= t('Enqueued') %></span>
20
20
  </a>
21
21
  </li>
22
22
  <li class="retries col-sm-1">
23
23
  <a href="<%= root_path %>retries">
24
- <span class="count"><%= number_with_delimiter(stats.retry_size) %></span>
24
+ <span id="txtRetries" class="count"><%= number_with_delimiter(stats.retry_size) %></span>
25
25
  <span class="desc"><%= t('Retries') %></span>
26
26
  </a>
27
27
  </li>
28
28
  <li class="scheduled col-sm-1">
29
29
  <a href="<%= root_path %>scheduled">
30
- <span class="count"><%= number_with_delimiter(stats.scheduled_size) %></span>
30
+ <span id="txtScheduled" class="count"><%= number_with_delimiter(stats.scheduled_size) %></span>
31
31
  <span class="desc"><%= t('Scheduled') %></span>
32
32
  </a>
33
33
  </li>
34
34
  <li class="dead col-sm-1">
35
35
  <a href="<%= root_path %>morgue">
36
- <span class="count"><%= number_with_delimiter(stats.dead_size) %></span>
36
+ <span id="txtDead" class="count"><%= number_with_delimiter(stats.dead_size) %></span>
37
37
  <span class="desc"><%= t('Dead') %></span>
38
38
  </a>
39
39
  </li>
data/web/views/busy.erb CHANGED
@@ -1,29 +1,57 @@
1
- <div class="row header">
2
- <div class="col-sm-8 pull-left flip">
3
- <h3><%= t('Processes') %></h3>
1
+ <div class="header-container">
2
+ <h1><%= t('Status') %></h1>
3
+ </div>
4
+
5
+ <div class="stats-wrapper">
6
+ <div class="stats-container">
7
+ <div class="stat">
8
+ <h3><%= s = processes.size; number_with_delimiter(s) %></h3>
9
+ <p><%= t('Processes') %></p>
10
+ </div>
11
+ <div class="stat">
12
+ <h3><%= x = processes.total_concurrency; number_with_delimiter(x) %></h3>
13
+ <p><%= t('Threads') %></p>
14
+ </div>
15
+ <div class="stat">
16
+ <h3><%= ws = workset.size; number_with_delimiter(ws) %></h3>
17
+ <p><%= t('Busy') %></p>
18
+ </div>
19
+ <div class="stat">
20
+ <h3><%= x == 0 ? 0 : ((ws / x.to_f) * 100).round(0) %>%</h3>
21
+ <p><%= t('Utilization') %></p>
22
+ </div>
23
+ <div class="stat">
24
+ <h3><%= format_memory(processes.total_rss) %></h3>
25
+ <p><%= t('RSS') %></p>
26
+ </div>
4
27
  </div>
5
- <div class="col-sm-4 pull-right flip">
28
+ </div>
29
+
30
+ <div class="header-container">
31
+ <h1><%= t('Processes') %></h1>
32
+ <div>
6
33
  <form method="POST" class="warning-messages">
7
34
  <%= csrf_tag %>
8
35
  <div class="btn-group pull-right flip">
9
- <button class="btn btn-warn" type="submit" name="quiet" value="1" data-confirm="<%= t('AreYouSure') %>"><%= t('QuietAll') %></button>
10
- <button class="btn btn-danger" type="submit" name="stop" value="1" data-confirm="<%= t('AreYouSure') %>"><%= t('StopAll') %></button>
36
+ <input class="btn btn-warn" type="submit" name="quiet" value="<%= t('QuietAll') %>" data-confirm="<%= t('AreYouSure') %>"/>
37
+ <input class="btn btn-danger" type="submit" name="stop" value="<%= t('StopAll') %>" data-confirm="<%= t('AreYouSure') %>"/>
11
38
  </div>
12
39
  </form>
13
40
  </div>
14
41
  </div>
15
42
 
16
43
  <div class="table_container">
17
- <table class="processes table table-hover table-bordered table-striped table-white">
44
+ <table class="processes table table-hover table-bordered table-striped">
18
45
  <thead>
19
46
  <th><%= t('Name') %></th>
20
47
  <th><%= t('Started') %></th>
21
- <th><%= t('Threads') %></th>
22
- <th><%= t('Busy') %></th>
48
+ <th class="col-sm-1"><%= t('RSS') %><a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Memory#rss"><span class="info-circle" title="Click to learn more about RSS">?</span></a></th>
49
+ <th class="col-sm-1"><%= t('Threads') %></th>
50
+ <th class="col-sm-1"><%= t('Busy') %></th>
23
51
  <th>&nbsp;</th>
24
52
  </thead>
25
53
  <% lead = processes.leader %>
26
- <% processes.each do |process| %>
54
+ <% sorted_processes.each do |process| %>
27
55
  <tr>
28
56
  <td class="box">
29
57
  <%= "#{process['hostname']}:#{process['pid']}" %>
@@ -31,6 +59,9 @@
31
59
  <% process.labels.each do |label| %>
32
60
  <span class="label label-info"><%= label %></span>
33
61
  <% end %>
62
+ <% if process.embedded? %>
63
+ <span class="label label-default">embedded</span>
64
+ <% end %>
34
65
  <% if process.stopping? %>
35
66
  <span class="label label-danger">quiet</span>
36
67
  <% end %>
@@ -39,36 +70,52 @@
39
70
  <% end %>
40
71
  <br>
41
72
  <b><%= "#{t('Queues')}: " %></b>
42
- <%= process['queues'] * ", " %>
73
+ <% if process.weights %>
74
+ <%= busy_weights(process.weights) %>
75
+ <% else %>
76
+ <%= process.queues.sort.join(", ") %>
77
+ <% end %>
78
+ <% if process.version != Sidekiq::VERSION %>
79
+ <br>
80
+ <b><%= "#{t('Version')}: " %></b>
81
+ <% if process.version %>
82
+ <%= process.version %>
83
+ <% else %>
84
+ <%= t('Unknown') %>
85
+ <% end %>
86
+ <% end %>
43
87
  </td>
44
88
  <td><%= relative_time(Time.at(process['started_at'])) %></td>
89
+ <td><%= format_memory(process['rss'].to_i) %></td>
45
90
  <td><%= process['concurrency'] %></td>
46
91
  <td><%= process['busy'] %></td>
47
92
  <td>
48
- <div class="btn-group pull-right flip">
93
+ <% unless process.embedded? %>
49
94
  <form method="POST">
50
95
  <%= csrf_tag %>
51
96
  <input type="hidden" name="identity" value="<%= process['identity'] %>"/>
52
- <% unless process.stopping? %>
53
- <button class="btn btn-warn" type="submit" name="quiet" value="1"><%= t('Quiet') %></button>
54
- <% end %>
55
- <button class="btn btn-danger" type="submit" name="stop" value="1"><%= t('Stop') %></button>
97
+
98
+ <div class="btn-group pull-right flip">
99
+ <% unless process.stopping? %><button class="btn btn-xs btn-warn" type="submit" name="quiet" value="1"><%= t('Quiet') %></button><% end %>
100
+ <button class="btn btn-xs btn-danger" type="submit" name="stop" value="1"><%= t('Stop') %></button>
101
+ </div>
56
102
  </form>
57
- </div>
103
+ <% end %>
58
104
  </td>
59
105
  </tr>
60
106
  <% end %>
61
107
  </table>
62
108
  </div>
63
109
 
64
- <div class="row header">
65
- <div class="col-sm-7">
66
- <h3><%= t('Jobs') %></h3>
67
- </div>
110
+ <div class="header-container">
111
+ <h1><%= t('Jobs') %></h1>
112
+ <% if @workset.size > 0 && @total_size > @count %>
113
+ <%= erb :_paging, locals: { url: "#{root_path}busy" } %>
114
+ <% end %>
68
115
  </div>
69
116
 
70
117
  <div class="table_container">
71
- <table class="workers table table-hover table-bordered table-striped table-white">
118
+ <table class="workers table table-hover table-bordered table-striped">
72
119
  <thead>
73
120
  <th><%= t('Process') %></th>
74
121
  <th><%= t('TID') %></th>
@@ -78,8 +125,8 @@
78
125
  <th><%= t('Arguments') %></th>
79
126
  <th><%= t('Started') %></th>
80
127
  </thead>
81
- <% workers.each do |process, thread, msg| %>
82
- <% job = Sidekiq::Job.new(msg['payload']) %>
128
+ <% @workset.each do |process, thread, msg| %>
129
+ <% job = Sidekiq::JobRecord.new(msg['payload']) %>
83
130
  <tr>
84
131
  <td><%= process %></td>
85
132
  <td><%= thread %></td>
@@ -87,7 +134,10 @@
87
134
  <td>
88
135
  <a href="<%= root_path %>queues/<%= msg['queue'] %>"><%= msg['queue'] %></a>
89
136
  </td>
90
- <td><%= job.display_class %></td>
137
+ <td>
138
+ <%= job.display_class %>
139
+ <%= display_tags(job, nil) %>
140
+ </td>
91
141
  <td>
92
142
  <div class="args"><%= display_args(job.display_args) %></div>
93
143
  </td>
@@ -1,73 +1,113 @@
1
+ <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
2
+ <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
3
+ <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
4
+ <script type="text/javascript" src="<%= root_path %>javascripts/dashboard-charts.js"></script>
1
5
  <script type="text/javascript" src="<%= root_path %>javascripts/dashboard.js"></script>
2
6
  <div class= "dashboard clearfix">
3
7
  <h3 >
4
8
  <%= t('Dashboard') %>
5
- <span class="beacon">
9
+ <span id="beacon" class="beacon">
6
10
  <span class="ring"></span>
7
11
  <span class="dot"></span>
8
12
  </span>
9
13
  </h3>
10
14
  <div class="interval-slider ltr">
11
15
  <span class="interval-slider-label"><%= t('PollingInterval') %>:</span>
12
- <span class="current-interval">5 sec</span>
16
+ <span id="sldr-text" class="current-interval">5 sec</span>
13
17
  <br/>
14
- <input type="range" min="2000" max="20000" step="1000" value="5000"/>
18
+ <input id="sldr" type="range" min="2000" max="20000" step="1000" value="5000"/>
15
19
  </div>
16
20
  </div>
17
21
 
18
22
  <div class="row chart">
19
- <div id="realtime" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>"></div>
20
- <div id="realtime-legend"></div>
23
+ <canvas id="realtime-chart"></canvas>
24
+ <script>
25
+ window.realtimeChart = new RealtimeChart(
26
+ document.getElementById("realtime-chart"),
27
+ <%= Sidekiq.dump_json({
28
+ processedLabel: t('Processed'),
29
+ failedLabel: t('Failed'),
30
+ labels: Array.new(50, ""),
31
+ processed: Array.new(50),
32
+ failed: Array.new(50),
33
+ updateUrl: "#{root_path}stats",
34
+ }) %>
35
+ )
36
+ </script>
37
+
38
+ <!-- start with a space in the legend so the height doesn't change when we add content dynamically -->
39
+ <div id="realtime-legend">&nbsp;</div>
40
+ <script>
41
+ realtimeChart.registerLegend(document.getElementById("realtime-legend"))
42
+ </script>
21
43
  </div>
22
44
 
23
- <div class="row chart">
24
- <h5>
25
- <span class="history-heading"><%= t('History') %></span>
45
+ <div class="row header">
46
+ <div class="col-sm-4 pull-left flip">
47
+ <h3><%= t('History') %></h3>
48
+ </div>
49
+ </div>
50
+ <div class="row chart">
51
+ <div>
26
52
  <a href="<%= root_path %>?days=7" class="history-graph <%= "active" if params[:days] == "7" %>"><%= t('OneWeek') %></a>
27
53
  <a href="<%= root_path %>" class="history-graph <%= "active" if params[:days].nil? || params[:days] == "30" %>"><%= t('OneMonth') %></a>
28
54
  <a href="<%= root_path %>?days=90" class="history-graph <%= "active" if params[:days] == "90" %>"><%= t('ThreeMonths') %></a>
29
55
  <a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
30
- </h5>
56
+ </div>
31
57
 
32
- <div id="history" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>" data-processed="<%= h Sidekiq.dump_json(@processed_history) %>" data-failed="<%= h Sidekiq.dump_json(@failed_history) %>" data-update-url="<%= root_path %>stats"></div>
33
- <div id="history-legend"></div>
58
+ <canvas id="history-chart"></canvas>
59
+ <script>
60
+ window.historyChart = new DashboardChart(
61
+ document.getElementById("history-chart"),
62
+ <%= Sidekiq.dump_json({
63
+ processedLabel: t('Processed'),
64
+ failedLabel: t('Failed'),
65
+ processed: @processed_history.to_a.reverse,
66
+ failed: @failed_history.to_a.reverse,
67
+ }) %>
68
+ )
69
+ </script>
34
70
  </div>
35
71
 
36
72
  <br/>
37
- <h5>Redis</h5>
38
- <div class="redis-wrapper">
73
+ <div class="row header">
74
+ <div class="col-sm-4 pull-left flip">
75
+ <h3>Redis</h3>
76
+ </div>
77
+ </div>
78
+ <div class="stats-wrapper">
39
79
  <div class="stats-container">
40
80
  <% if @redis_info.fetch("redis_version", nil) %>
41
81
  <div class="stat">
42
- <h3 class="redis_version"><%= @redis_info.fetch("redis_version") %></h3>
82
+ <h3 id="redis_version"><%= @redis_info.fetch("redis_version") %></h3>
43
83
  <p><%= t('Version') %></p>
44
84
  </div>
45
85
  <% end %>
46
86
 
47
87
  <% if @redis_info.fetch("uptime_in_days", nil) %>
48
88
  <div class="stat">
49
- <h3 class="uptime_in_days"><%= @redis_info.fetch("uptime_in_days") %></h3>
89
+ <h3 id="uptime_in_days"><%= @redis_info.fetch("uptime_in_days") %></h3>
50
90
  <p><%= t('Uptime') %></p>
51
91
  </div>
52
92
  <% end %>
53
93
 
54
94
  <% if @redis_info.fetch("connected_clients", nil) %>
55
95
  <div class="stat">
56
- <h3 class="connected_clients"><%= @redis_info.fetch("connected_clients") %></h3>
96
+ <h3 id="connected_clients"><%= @redis_info.fetch("connected_clients") %></h3>
57
97
  <p><%= t('Connections') %></p>
58
98
  </div>
59
99
  <% end %>
60
100
 
61
101
  <% if @redis_info.fetch("used_memory_human", nil) %>
62
102
  <div class="stat">
63
- <h3 class="used_memory_human"><%= @redis_info.fetch("used_memory_human") %></h3>
103
+ <h3 id="used_memory_human"><%= @redis_info.fetch("used_memory_human") %></h3>
64
104
  <p><%= t('MemoryUsage') %></p>
65
105
  </div>
66
106
  <% end %>
67
107
 
68
108
  <% if @redis_info.fetch("used_memory_peak_human", nil) %>
69
109
  <div class="stat">
70
- <h3 class="used_memory_peak_human"><%= @redis_info.fetch("used_memory_peak_human") %></h3>
110
+ <h3 id="used_memory_peak_human"><%= @redis_info.fetch("used_memory_peak_human") %></h3>
71
111
  <p><%= t('PeakMemoryUsage') %></p>
72
112
  </div>
73
113
  <% end %>
data/web/views/dead.erb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <h3><%= t('Error') %></h3>
4
4
  <div class="table_container">
5
- <table class="error table table-bordered table-striped">
5
+ <table class="error table table-bordered table-striped table-hover">
6
6
  <tbody>
7
7
  <tr>
8
8
  <th><%= t('ErrorClass') %></th>
@@ -14,11 +14,11 @@
14
14
  <th><%= t('ErrorMessage') %></th>
15
15
  <td><%= h(@dead['error_message']) %></td>
16
16
  </tr>
17
- <% if !@dead['error_backtrace'].nil? %>
17
+ <% if @dead.error_backtrace %>
18
18
  <tr>
19
19
  <th><%= t('ErrorBacktrace') %></th>
20
20
  <td>
21
- <code><%= @dead['error_backtrace'].join("<br/>") %></code>
21
+ <code><%= @dead.error_backtrace.join("<br/>") %></code>
22
22
  </td>
23
23
  </tr>
24
24
  <% end %>
data/web/views/layout.erb CHANGED
@@ -11,16 +11,18 @@
11
11
  <% end %>
12
12
 
13
13
  <link href="<%= root_path %>stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
14
+ <link href="<%= root_path %>stylesheets/application-dark.css" media="screen and (prefers-color-scheme: dark)" rel="stylesheet" type="text/css" />
14
15
  <% if rtl? %>
15
16
  <link href="<%= root_path %>stylesheets/application-rtl.css" media="screen" rel="stylesheet" type="text/css" />
16
17
  <% end %>
17
18
 
19
+ <link rel="apple-touch-icon" href="<%= root_path %>images/apple-touch-icon.png">
18
20
  <link rel="shortcut icon" type="image/ico" href="<%= root_path %>images/favicon.ico" />
19
21
  <script type="text/javascript" src="<%= root_path %>javascripts/application.js"></script>
20
22
  <meta name="google" content="notranslate" />
21
23
  <%= display_custom_head %>
22
24
  </head>
23
- <body class="admin" data-poll-path="<%= poll_path %>" data-locale="<%= locale %>">
25
+ <body class="admin" data-locale="<%= locale %>">
24
26
  <%= erb :_nav %>
25
27
  <div id="page">
26
28
  <div class="container">
@@ -0,0 +1,82 @@
1
+ <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
2
+ <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
3
+ <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
4
+ <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
5
+
6
+ <div class="header-container">
7
+ <div class="page-title-container">
8
+ <h1><%= t('Metrics') %></h1>
9
+
10
+ <a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Metrics"><span class="info-circle" title="Click to learn more about metrics">?</span></a>
11
+ </div>
12
+
13
+ <%= erb :_metrics_period_select, locals: { periods: @periods, period: @period, path: "#{root_path}metrics" } %>
14
+ </div>
15
+
16
+ <%
17
+ table_limit = 20
18
+ chart_limit = 5
19
+ job_results = @query_result.job_results.sort_by { |(kls, jr)| jr.totals["s"] }.reverse.first(table_limit)
20
+ visible_kls = job_results.first(chart_limit).map(&:first)
21
+ %>
22
+
23
+ <% if job_results.any? %>
24
+ <canvas id="job-metrics-overview-chart"></canvas>
25
+
26
+ <script>
27
+ window.jobMetricsChart = new JobMetricsOverviewChart(
28
+ document.getElementById("job-metrics-overview-chart"),
29
+ <%= Sidekiq.dump_json({
30
+ series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
31
+ marks: @query_result.marks.map { |m| [m.bucket, m.label] },
32
+ labels: @query_result.buckets,
33
+ visibleKls: visible_kls,
34
+ yLabel: t('TotalExecutionTime'),
35
+ units: t('Seconds').downcase,
36
+ markLabel: t('Deploy'),
37
+ }) %>
38
+ )
39
+ </script>
40
+ <% end %>
41
+
42
+ <div class="table_container">
43
+ <table class="table table-bordered table-striped table-hover">
44
+ <tbody>
45
+ <tr>
46
+ <th><%= t('Name') %></th>
47
+ <th><%= t('Success') %></th>
48
+ <th><%= t('Failure') %></th>
49
+ <th><%= t('TotalExecutionTime') %></th>
50
+ <th><%= t('AvgExecutionTime') %></th>
51
+ </tr>
52
+ <% if job_results.any? %>
53
+ <% job_results.each_with_index do |(kls, jr), i| %>
54
+ <tr>
55
+ <td>
56
+ <div class="metrics-swatch-wrapper">
57
+ <% id = "metrics-swatch-#{kls}" %>
58
+ <input
59
+ type="checkbox"
60
+ id="<%= id %>"
61
+ class="metrics-swatch"
62
+ value="<%= kls %>"
63
+ <%= visible_kls.include?(kls) ? 'checked' : '' %>
64
+ />
65
+ <code><a href="<%= root_path %>metrics/<%= kls %>?period=<%= @period %>"><%= kls %></a></code>
66
+ </div>
67
+ <script>jobMetricsChart.registerSwatch("<%= id %>")</script>
68
+ </td>
69
+ <td><%= jr.dig("totals", "p") - jr.dig("totals", "f") %></td>
70
+ <td><%= jr.dig("totals", "f") %></td>
71
+ <td><%= jr.dig("totals", "s").round(2) %> seconds</td>
72
+ <td><%= jr.total_avg("s").round(2) %> seconds</td>
73
+ </tr>
74
+ <% end %>
75
+ <% else %>
76
+ <tr><td colspan=5><%= t("NoDataFound") %></td></tr>
77
+ <% end %>
78
+ </tbody>
79
+ </table>
80
+ </div>
81
+
82
+ <p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
@@ -0,0 +1,68 @@
1
+ <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
2
+ <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
3
+ <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
4
+ <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
5
+
6
+ <%
7
+ job_result = @query_result.job_results[@name]
8
+ hist_totals = job_result.hist.values.first.zip(*job_result.hist.values[1..-1]).map(&:sum).reverse
9
+ bucket_labels = Sidekiq::Metrics::Histogram::LABELS
10
+ bucket_intervals = Sidekiq::Metrics::Histogram::BUCKET_INTERVALS
11
+ %>
12
+
13
+ <% if job_result.totals["s"] > 0 %>
14
+ <div class="header-container">
15
+ <div class="page-title-container">
16
+ <h1>
17
+ <a href="<%= root_path %>metrics?period=<%= @period %>"><%= t('Metrics') %></a> /
18
+ <%= h @name %>
19
+ </h1>
20
+
21
+ <a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Metrics"><span class="info-circle" title="Click to learn more about metrics">?</span></a>
22
+ </div>
23
+
24
+ <%= erb :_metrics_period_select, locals: { periods: @periods, period: @period, path: "#{root_path}metrics/#{@name}" } %>
25
+ </div>
26
+
27
+ <canvas id="hist-totals-chart"></canvas>
28
+
29
+ <script>
30
+ window.histTotalsChart = new HistTotalsChart(
31
+ document.getElementById("hist-totals-chart"),
32
+ <%= Sidekiq.dump_json({
33
+ series: hist_totals,
34
+ labels: bucket_labels,
35
+ xLabel: t('ExecutionTime'),
36
+ yLabel: t('Jobs'),
37
+ units: t('Jobs').downcase,
38
+ }) %>
39
+ )
40
+ </script>
41
+
42
+ <canvas id="hist-bubble-chart"></canvas>
43
+
44
+ <script>
45
+ window.histBubbleChart = new HistBubbleChart(
46
+ document.getElementById("hist-bubble-chart"),
47
+ <%= Sidekiq.dump_json({
48
+ hist: job_result.hist,
49
+ marks: @query_result.marks.map { |m| [m.bucket, m.label] },
50
+ labels: @query_result.buckets,
51
+ histIntervals: bucket_intervals,
52
+ yLabel: t('ExecutionTime'),
53
+ markLabel: t('Deploy'),
54
+ yUnits: t('Seconds').downcase,
55
+ zUnits: t('Jobs').downcase,
56
+ }) %>
57
+ )
58
+ </script>
59
+
60
+ <p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
61
+ <% else %>
62
+ <h1>
63
+ <a href="<%= root_path %>/metrics"><%= t('Metrics') %></a> /
64
+ <%= h @name %>
65
+ </h1>
66
+
67
+ <div class="alert alert-success"><%= t('NoJobMetricsFound') %></div>
68
+ <% end %>
data/web/views/morgue.erb CHANGED
@@ -1,20 +1,16 @@
1
- <header class="row">
2
- <div class="col-sm-5">
3
- <h3><%= t('DeadJobs') %></h3>
4
- </div>
1
+ <div class="header-container">
2
+ <h1><%= t('DeadJobs') %></h1>
5
3
  <% if @dead.size > 0 && @total_size > @count %>
6
- <div class="col-sm-4">
7
- <%= erb :_paging, locals: { url: "#{root_path}morgue" } %>
8
- </div>
4
+ <%= erb :_paging, locals: { url: "#{root_path}morgue" } %>
9
5
  <% end %>
10
6
  <%= filtering('dead') %>
11
- </header>
7
+ </div>
12
8
 
13
9
  <% if @dead.size > 0 %>
14
10
  <form action="<%= root_path %>morgue" method="post">
15
11
  <%= csrf_tag %>
16
12
  <div class="table_container">
17
- <table class="table table-striped table-bordered table-white">
13
+ <table class="table table-striped table-bordered table-hover">
18
14
  <thead>
19
15
  <tr>
20
16
  <th class="table-checkbox checkbox-column">
@@ -33,7 +29,7 @@
33
29
  <tr>
34
30
  <td class="table-checkbox">
35
31
  <label>
36
- <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
32
+ <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
37
33
  </label>
38
34
  </td>
39
35
  <td>
@@ -42,7 +38,10 @@
42
38
  <td>
43
39
  <a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
44
40
  </td>
45
- <td><%= entry.display_class %></td>
41
+ <td>
42
+ <%= entry.display_class %>
43
+ <%= display_tags(entry, "dead") %>
44
+ </td>
46
45
  <td>
47
46
  <div class="args"><%= display_args(entry.display_args) %></div>
48
47
  </td>
@@ -55,18 +54,18 @@
55
54
  <% end %>
56
55
  </table>
57
56
  </div>
58
- <input class="btn btn-primary btn-xs pull-left flip" type="submit" name="retry" value="<%= t('RetryNow') %>" />
59
- <input class="btn btn-danger btn-xs pull-left flip" type="submit" name="delete" value="<%= t('Delete') %>" />
57
+ <input class="btn btn-primary pull-left flip" type="submit" name="retry" value="<%= t('RetryNow') %>" />
58
+ <input class="btn btn-danger pull-left flip" type="submit" name="delete" value="<%= t('Delete') %>" />
60
59
  </form>
61
60
 
62
61
  <% unfiltered? do %>
63
62
  <form action="<%= root_path %>morgue/all/delete" method="post">
64
63
  <%= csrf_tag %>
65
- <input class="btn btn-danger btn-xs pull-right flip" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSure') %>" />
64
+ <input class="btn btn-danger pull-right flip" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSure') %>" />
66
65
  </form>
67
66
  <form action="<%= root_path %>morgue/all/retry" method="post">
68
67
  <%= csrf_tag %>
69
- <input class="btn btn-danger btn-xs pull-right flip" type="submit" name="retry" value="<%= t('RetryAll') %>" data-confirm="<%= t('AreYouSure') %>" />
68
+ <input class="btn btn-danger pull-right flip" type="submit" name="retry" value="<%= t('RetryAll') %>" data-confirm="<%= t('AreYouSure') %>" />
70
69
  </form>
71
70
  <% end %>
72
71