sidekiq 6.2.2 → 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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +279 -11
  3. data/LICENSE.txt +9 -0
  4. data/README.md +45 -32
  5. data/bin/sidekiq +4 -9
  6. data/bin/sidekiqload +207 -117
  7. data/bin/sidekiqmon +4 -1
  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 +331 -187
  13. data/lib/sidekiq/capsule.rb +127 -0
  14. data/lib/sidekiq/cli.rb +94 -81
  15. data/lib/sidekiq/client.rb +100 -96
  16. data/lib/sidekiq/{util.rb → component.rb} +14 -41
  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 +26 -26
  21. data/lib/sidekiq/job.rb +371 -5
  22. data/lib/sidekiq/job_logger.rb +16 -28
  23. data/lib/sidekiq/job_retry.rb +85 -59
  24. data/lib/sidekiq/job_util.rb +105 -0
  25. data/lib/sidekiq/launcher.rb +106 -94
  26. data/lib/sidekiq/logger.rb +9 -44
  27. data/lib/sidekiq/manager.rb +40 -41
  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 +96 -51
  32. data/lib/sidekiq/middleware/current_attributes.rb +56 -0
  33. data/lib/sidekiq/middleware/i18n.rb +6 -4
  34. data/lib/sidekiq/middleware/modules.rb +21 -0
  35. data/lib/sidekiq/monitor.rb +17 -4
  36. data/lib/sidekiq/paginator.rb +17 -9
  37. data/lib/sidekiq/processor.rb +60 -60
  38. data/lib/sidekiq/rails.rb +25 -6
  39. data/lib/sidekiq/redis_client_adapter.rb +96 -0
  40. data/lib/sidekiq/redis_connection.rb +17 -88
  41. data/lib/sidekiq/ring_buffer.rb +29 -0
  42. data/lib/sidekiq/scheduled.rb +101 -44
  43. data/lib/sidekiq/testing/inline.rb +4 -4
  44. data/lib/sidekiq/testing.rb +41 -68
  45. data/lib/sidekiq/transaction_aware_client.rb +44 -0
  46. data/lib/sidekiq/version.rb +2 -1
  47. data/lib/sidekiq/web/action.rb +3 -3
  48. data/lib/sidekiq/web/application.rb +47 -13
  49. data/lib/sidekiq/web/csrf_protection.rb +3 -3
  50. data/lib/sidekiq/web/helpers.rb +36 -33
  51. data/lib/sidekiq/web.rb +10 -17
  52. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  53. data/lib/sidekiq.rb +86 -201
  54. data/sidekiq.gemspec +12 -10
  55. data/web/assets/javascripts/application.js +131 -60
  56. data/web/assets/javascripts/base-charts.js +106 -0
  57. data/web/assets/javascripts/chart.min.js +13 -0
  58. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  59. data/web/assets/javascripts/dashboard-charts.js +166 -0
  60. data/web/assets/javascripts/dashboard.js +36 -273
  61. data/web/assets/javascripts/metrics.js +264 -0
  62. data/web/assets/stylesheets/application-dark.css +23 -23
  63. data/web/assets/stylesheets/application-rtl.css +2 -95
  64. data/web/assets/stylesheets/application.css +73 -402
  65. data/web/locales/ar.yml +70 -70
  66. data/web/locales/cs.yml +62 -62
  67. data/web/locales/da.yml +60 -53
  68. data/web/locales/de.yml +65 -65
  69. data/web/locales/el.yml +43 -24
  70. data/web/locales/en.yml +82 -69
  71. data/web/locales/es.yml +68 -68
  72. data/web/locales/fa.yml +65 -65
  73. data/web/locales/fr.yml +81 -67
  74. data/web/locales/gd.yml +99 -0
  75. data/web/locales/he.yml +65 -64
  76. data/web/locales/hi.yml +59 -59
  77. data/web/locales/it.yml +53 -53
  78. data/web/locales/ja.yml +73 -68
  79. data/web/locales/ko.yml +52 -52
  80. data/web/locales/lt.yml +66 -66
  81. data/web/locales/nb.yml +61 -61
  82. data/web/locales/nl.yml +52 -52
  83. data/web/locales/pl.yml +45 -45
  84. data/web/locales/pt-br.yml +63 -55
  85. data/web/locales/pt.yml +51 -51
  86. data/web/locales/ru.yml +67 -66
  87. data/web/locales/sv.yml +53 -53
  88. data/web/locales/ta.yml +60 -60
  89. data/web/locales/uk.yml +62 -61
  90. data/web/locales/ur.yml +64 -64
  91. data/web/locales/vi.yml +67 -67
  92. data/web/locales/zh-cn.yml +43 -16
  93. data/web/locales/zh-tw.yml +42 -8
  94. data/web/views/_footer.erb +6 -3
  95. data/web/views/_job_info.erb +18 -2
  96. data/web/views/_metrics_period_select.erb +12 -0
  97. data/web/views/_nav.erb +1 -1
  98. data/web/views/_paging.erb +2 -0
  99. data/web/views/_poll_link.erb +3 -6
  100. data/web/views/_summary.erb +7 -7
  101. data/web/views/busy.erb +44 -28
  102. data/web/views/dashboard.erb +44 -12
  103. data/web/views/layout.erb +1 -1
  104. data/web/views/metrics.erb +82 -0
  105. data/web/views/metrics_for_job.erb +68 -0
  106. data/web/views/morgue.erb +5 -9
  107. data/web/views/queue.erb +24 -24
  108. data/web/views/queues.erb +4 -2
  109. data/web/views/retries.erb +5 -9
  110. data/web/views/scheduled.erb +12 -13
  111. metadata +62 -31
  112. data/LICENSE +0 -9
  113. data/lib/generators/sidekiq/worker_generator.rb +0 -57
  114. data/lib/sidekiq/delay.rb +0 -41
  115. data/lib/sidekiq/exception_handler.rb +0 -27
  116. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  117. data/lib/sidekiq/extensions/active_record.rb +0 -43
  118. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  119. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  120. data/lib/sidekiq/worker.rb +0 -244
@@ -0,0 +1,12 @@
1
+ <div>
2
+ <select class="form-control" onchange="window.location.href = '<%= path %>?period=' + event.target.value">
3
+ <% periods.each_key do |code| %>
4
+
5
+ <% if code == period %>
6
+ <option selected value="<%= code %>"><%= code %></option>
7
+ <% else %>
8
+ <option value="<%= code %>"><%= code %></option>
9
+ <% end %>
10
+ <% end %>
11
+ </select>
12
+ </div>
data/web/views/_nav.erb CHANGED
@@ -1,7 +1,7 @@
1
1
  <div class="navbar navbar-default navbar-fixed-top">
2
2
  <div class="container-fluid">
3
3
  <div class="navbar-header" data-navbar="static">
4
- <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-menu">
4
+ <button type="button" class="navbar-toggle collapsed" data-toggle="navbar-menu" data-target="#navbar-menu">
5
5
  <span class="icon-bar"></span>
6
6
  <span class="icon-bar"></span>
7
7
  <span class="icon-bar"></span>
@@ -1,3 +1,4 @@
1
+ <div>
1
2
  <% if @total_size > @count %>
2
3
  <ul class="pagination pull-right flip">
3
4
  <li class="<%= 'disabled' if @current_page == 1 %>">
@@ -21,3 +22,4 @@
21
22
  </li>
22
23
  </ul>
23
24
  <% end %>
25
+ </div>
@@ -1,7 +1,4 @@
1
- <% if current_path != '' %>
2
- <% if params[:poll] %>
3
- <a id="live-poll" class="btn btn-primary active" href="<%= root_path + current_path %>"><%= t('StopPolling') %></a>
4
- <% else %>
5
- <a id="live-poll" class="btn btn-primary" href="<%= root_path + current_path %>?<%= qparams(poll: true) %>"><%= t('LivePoll') %></a>
6
- <% end %>
1
+ <% if pollable? %>
2
+ <a class="live-poll-start live-poll btn btn-primary"><%= t('LivePoll') %></a>
3
+ <a class="live-poll-stop live-poll btn btn-primary active"><%= t('StopPolling') %></a>
7
4
  <% end %>
@@ -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,7 +1,5 @@
1
- <div class="row header">
2
- <div class="col-sm-4 pull-left flip">
3
- <h3><%= t('Status') %></h3>
4
- </div>
1
+ <div class="header-container">
2
+ <h1><%= t('Status') %></h1>
5
3
  </div>
6
4
 
7
5
  <div class="stats-wrapper">
@@ -15,7 +13,7 @@
15
13
  <p><%= t('Threads') %></p>
16
14
  </div>
17
15
  <div class="stat">
18
- <h3><%= ws = workers.size; number_with_delimiter(ws) %></h3>
16
+ <h3><%= ws = workset.size; number_with_delimiter(ws) %></h3>
19
17
  <p><%= t('Busy') %></p>
20
18
  </div>
21
19
  <div class="stat">
@@ -29,32 +27,31 @@
29
27
  </div>
30
28
  </div>
31
29
 
32
- <div class="row header">
33
- <div class="col-sm-4 pull-left flip">
34
- <h3><%= t('Processes') %></h3>
35
- </div>
36
- <div class="col-sm-3 pull-right flip">
30
+ <div class="header-container">
31
+ <h1><%= t('Processes') %></h1>
32
+ <div>
37
33
  <form method="POST" class="warning-messages">
38
34
  <%= csrf_tag %>
39
35
  <div class="btn-group pull-right flip">
40
- <button class="btn btn-warn" type="submit" name="quiet" value="1" data-confirm="<%= t('AreYouSure') %>"><%= t('QuietAll') %></button>
41
- <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') %>"/>
42
38
  </div>
43
39
  </form>
44
40
  </div>
45
41
  </div>
42
+
46
43
  <div class="table_container">
47
44
  <table class="processes table table-hover table-bordered table-striped">
48
45
  <thead>
49
46
  <th><%= t('Name') %></th>
50
47
  <th><%= t('Started') %></th>
51
- <th class="col-sm-1"><%= t('RSS') %><a href="https://github.com/mperham/sidekiq/wiki/Memory#rss"><span class="info-circle" title="Click to learn more about RSS">?</span></a></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>
52
49
  <th class="col-sm-1"><%= t('Threads') %></th>
53
50
  <th class="col-sm-1"><%= t('Busy') %></th>
54
51
  <th>&nbsp;</th>
55
52
  </thead>
56
53
  <% lead = processes.leader %>
57
- <% processes.each do |process| %>
54
+ <% sorted_processes.each do |process| %>
58
55
  <tr>
59
56
  <td class="box">
60
57
  <%= "#{process['hostname']}:#{process['pid']}" %>
@@ -62,6 +59,9 @@
62
59
  <% process.labels.each do |label| %>
63
60
  <span class="label label-info"><%= label %></span>
64
61
  <% end %>
62
+ <% if process.embedded? %>
63
+ <span class="label label-default">embedded</span>
64
+ <% end %>
65
65
  <% if process.stopping? %>
66
66
  <span class="label label-danger">quiet</span>
67
67
  <% end %>
@@ -70,32 +70,48 @@
70
70
  <% end %>
71
71
  <br>
72
72
  <b><%= "#{t('Queues')}: " %></b>
73
- <%= process.queues.join(", ") %>
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 %>
74
87
  </td>
75
88
  <td><%= relative_time(Time.at(process['started_at'])) %></td>
76
89
  <td><%= format_memory(process['rss'].to_i) %></td>
77
90
  <td><%= process['concurrency'] %></td>
78
91
  <td><%= process['busy'] %></td>
79
92
  <td>
80
- <form method="POST">
81
- <%= csrf_tag %>
82
- <input type="hidden" name="identity" value="<%= process['identity'] %>"/>
93
+ <% unless process.embedded? %>
94
+ <form method="POST">
95
+ <%= csrf_tag %>
96
+ <input type="hidden" name="identity" value="<%= process['identity'] %>"/>
83
97
 
84
- <div class="btn-group pull-right flip">
85
- <% unless process.stopping? %><button class="btn btn-xs btn-warn" type="submit" name="quiet" value="1"><%= t('Quiet') %></button><% end %>
86
- <button class="btn btn-xs btn-danger" type="submit" name="stop" value="1"><%= t('Stop') %></button>
87
- </div>
88
- </form>
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>
102
+ </form>
103
+ <% end %>
89
104
  </td>
90
105
  </tr>
91
106
  <% end %>
92
107
  </table>
93
108
  </div>
94
109
 
95
- <div class="row header">
96
- <div class="col-sm-7">
97
- <h3><%= t('Jobs') %></h3>
98
- </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 %>
99
115
  </div>
100
116
 
101
117
  <div class="table_container">
@@ -109,7 +125,7 @@
109
125
  <th><%= t('Arguments') %></th>
110
126
  <th><%= t('Started') %></th>
111
127
  </thead>
112
- <% workers.each do |process, thread, msg| %>
128
+ <% @workset.each do |process, thread, msg| %>
113
129
  <% job = Sidekiq::JobRecord.new(msg['payload']) %>
114
130
  <tr>
115
131
  <td><%= process %></td>
@@ -1,23 +1,45 @@
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
45
  <div class="row header">
@@ -33,8 +55,18 @@
33
55
  <a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
34
56
  </div>
35
57
 
36
- <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>
37
- <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>
38
70
  </div>
39
71
 
40
72
  <br/>
@@ -47,35 +79,35 @@
47
79
  <div class="stats-container">
48
80
  <% if @redis_info.fetch("redis_version", nil) %>
49
81
  <div class="stat">
50
- <h3 class="redis_version"><%= @redis_info.fetch("redis_version") %></h3>
82
+ <h3 id="redis_version"><%= @redis_info.fetch("redis_version") %></h3>
51
83
  <p><%= t('Version') %></p>
52
84
  </div>
53
85
  <% end %>
54
86
 
55
87
  <% if @redis_info.fetch("uptime_in_days", nil) %>
56
88
  <div class="stat">
57
- <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>
58
90
  <p><%= t('Uptime') %></p>
59
91
  </div>
60
92
  <% end %>
61
93
 
62
94
  <% if @redis_info.fetch("connected_clients", nil) %>
63
95
  <div class="stat">
64
- <h3 class="connected_clients"><%= @redis_info.fetch("connected_clients") %></h3>
96
+ <h3 id="connected_clients"><%= @redis_info.fetch("connected_clients") %></h3>
65
97
  <p><%= t('Connections') %></p>
66
98
  </div>
67
99
  <% end %>
68
100
 
69
101
  <% if @redis_info.fetch("used_memory_human", nil) %>
70
102
  <div class="stat">
71
- <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>
72
104
  <p><%= t('MemoryUsage') %></p>
73
105
  </div>
74
106
  <% end %>
75
107
 
76
108
  <% if @redis_info.fetch("used_memory_peak_human", nil) %>
77
109
  <div class="stat">
78
- <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>
79
111
  <p><%= t('PeakMemoryUsage') %></p>
80
112
  </div>
81
113
  <% end %>
data/web/views/layout.erb CHANGED
@@ -22,7 +22,7 @@
22
22
  <meta name="google" content="notranslate" />
23
23
  <%= display_custom_head %>
24
24
  </head>
25
- <body class="admin" data-poll-path="<%= poll_path %>" data-locale="<%= locale %>">
25
+ <body class="admin" data-locale="<%= locale %>">
26
26
  <%= erb :_nav %>
27
27
  <div id="page">
28
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,14 +1,10 @@
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">
@@ -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>
data/web/views/queue.erb CHANGED
@@ -1,50 +1,50 @@
1
- <header class="row">
2
- <div class="col-sm-5">
3
- <h3>
4
- <%= t('CurrentMessagesInQueue', :queue => h(@name)) %>
5
- <% if @queue.paused? %>
6
- <span class="label label-danger"><%= t('Paused') %></span>
7
- <% end %>
8
- <span class="badge badge-secondary"><%= number_with_delimiter(@total_size) %></span>
9
- </h3>
10
- </div>
11
- <div class="col-sm-4 pull-right flip">
12
- <%= erb :_paging, locals: { url: "#{root_path}queues/#{CGI.escape(@name)}" } %>
13
- </div>
14
- </header>
1
+ <div class="header-container">
2
+ <h1><%= t('CurrentMessagesInQueue', :queue => h(@name)) %>
3
+ <% if @queue.paused? %>
4
+ <span class="label label-danger"><%= t('Paused') %></span>
5
+ <% end %>
6
+ <span class="badge badge-secondary"><%= number_with_delimiter(@total_size) %></span>
7
+ </h1>
8
+ <%= erb :_paging, locals: { url: "#{root_path}queues/#{CGI.escape(@name)}" } %>
9
+ </div>
10
+
15
11
  <div class="table_container">
16
12
  <table class="queue table table-hover table-bordered table-striped">
17
13
  <thead>
18
14
  <th><a href="<%= url %>?direction=<%= params[:direction] == 'asc' ? 'desc' : 'asc' %>"># <%= sort_direction_label %></a></th>
19
15
  <th><%= t('Job') %></th>
20
16
  <th><%= t('Arguments') %></th>
17
+ <th><%= t('Context') %></th>
21
18
  <th></th>
22
19
  </thead>
23
- <% @messages.each_with_index do |msg, index| %>
24
- <tr>
20
+ <% @jobs.each_with_index do |job, index| %>
21
+ <tr title="<%= job.jid %>">
25
22
  <% if params[:direction] == 'asc' %>
26
23
  <td><%= @count * (@current_page - 1) + index + 1 %></td>
27
24
  <% else %>
28
25
  <td><%= @total_size - (@count * (@current_page - 1) + index) %></td>
29
26
  <% end %>
30
27
  <td>
31
- <%= h(msg.display_class) %>
32
- <%= display_tags(msg, nil) %>
28
+ <%= h(job.display_class) %>
29
+ <%= display_tags(job, nil) %>
33
30
  </td>
34
31
  <td>
35
- <% a = msg.display_args %>
32
+ <% a = job.display_args %>
36
33
  <% if a.inspect.size > 100 %>
37
- <span class="worker_<%= index %>"><%= h(a.inspect[0..100]) + "... " %></span>
38
- <button data-toggle="collapse" data-target=".worker_<%= index %>" class="btn btn-default btn-xs"><%= t('ShowAll') %></button>
39
- <div class="toggle worker_<%= index %>"><%= display_args(a) %></div>
34
+ <span id="job_<%= index %>"><%= h(a.inspect[0..100]) + "... " %></span>
35
+ <button data-toggle="job_<%= index %>_full" class="btn btn-default btn-xs"><%= t('ShowAll') %></button>
36
+ <div class="toggle" id="job_<%= index %>_full"><%= display_args(a) %></div>
40
37
  <% else %>
41
- <%= display_args(msg.display_args) %>
38
+ <%= display_args(job.display_args) %>
42
39
  <% end %>
43
40
  </td>
41
+ <td>
42
+ <%= h(job["cattr"].inspect) if job["cattr"]&.any? %>
43
+ </td>
44
44
  <td>
45
45
  <form action="<%= root_path %>queues/<%= CGI.escape(@name) %>/delete" method="post">
46
46
  <%= csrf_tag %>
47
- <input name="key_val" value="<%= h msg.value %>" type="hidden" />
47
+ <input name="key_val" value="<%= h job.value %>" type="hidden" />
48
48
  <input class="btn btn-danger btn-xs" type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSure') %>" />
49
49
  </form>
50
50
  </td>
data/web/views/queues.erb CHANGED
@@ -1,4 +1,6 @@
1
- <h3><%= t('Queues') %></h3>
1
+ <div class="header-container">
2
+ <h1><%= t('Queues') %></h1>
3
+ </div>
2
4
 
3
5
  <div class="table_container">
4
6
  <table class="queues table table-hover table-bordered table-striped">
@@ -21,7 +23,7 @@
21
23
  <td class="delete-confirm">
22
24
  <form action="<%=root_path %>queues/<%= CGI.escape(queue.name) %>" method="post">
23
25
  <%= csrf_tag %>
24
- <input class="btn btn-danger" type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSureDeleteQueue', :queue => h(queue.name)) %>" />
26
+ <input class="btn btn-danger" type="submit" name="delete" title="This will delete all jobs within the queue, it will reappear if you push more jobs to it in the future." value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSureDeleteQueue', :queue => h(queue.name)) %>" />
25
27
 
26
28
  <% if Sidekiq.pro? %>
27
29
  <% if queue.paused? %>