sidekiq 7.0.0 → 7.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +261 -13
  3. data/README.md +34 -27
  4. data/bin/multi_queue_bench +271 -0
  5. data/bin/sidekiqload +204 -109
  6. data/bin/sidekiqmon +3 -0
  7. data/lib/sidekiq/api.rb +151 -23
  8. data/lib/sidekiq/capsule.rb +20 -0
  9. data/lib/sidekiq/cli.rb +9 -4
  10. data/lib/sidekiq/client.rb +40 -24
  11. data/lib/sidekiq/component.rb +3 -1
  12. data/lib/sidekiq/config.rb +32 -12
  13. data/lib/sidekiq/deploy.rb +5 -5
  14. data/lib/sidekiq/embedded.rb +3 -3
  15. data/lib/sidekiq/fetch.rb +3 -5
  16. data/lib/sidekiq/iterable_job.rb +53 -0
  17. data/lib/sidekiq/job/interrupt_handler.rb +22 -0
  18. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  19. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  20. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  21. data/lib/sidekiq/job/iterable.rb +231 -0
  22. data/lib/sidekiq/job.rb +17 -10
  23. data/lib/sidekiq/job_logger.rb +24 -11
  24. data/lib/sidekiq/job_retry.rb +34 -11
  25. data/lib/sidekiq/job_util.rb +51 -15
  26. data/lib/sidekiq/launcher.rb +38 -22
  27. data/lib/sidekiq/logger.rb +1 -1
  28. data/lib/sidekiq/metrics/query.rb +6 -3
  29. data/lib/sidekiq/metrics/shared.rb +4 -4
  30. data/lib/sidekiq/metrics/tracking.rb +9 -3
  31. data/lib/sidekiq/middleware/chain.rb +12 -9
  32. data/lib/sidekiq/middleware/current_attributes.rb +70 -17
  33. data/lib/sidekiq/monitor.rb +17 -4
  34. data/lib/sidekiq/paginator.rb +4 -4
  35. data/lib/sidekiq/processor.rb +41 -27
  36. data/lib/sidekiq/rails.rb +18 -8
  37. data/lib/sidekiq/redis_client_adapter.rb +31 -35
  38. data/lib/sidekiq/redis_connection.rb +29 -7
  39. data/lib/sidekiq/scheduled.rb +4 -4
  40. data/lib/sidekiq/testing.rb +27 -8
  41. data/lib/sidekiq/transaction_aware_client.rb +7 -0
  42. data/lib/sidekiq/version.rb +1 -1
  43. data/lib/sidekiq/web/action.rb +10 -4
  44. data/lib/sidekiq/web/application.rb +113 -16
  45. data/lib/sidekiq/web/csrf_protection.rb +9 -6
  46. data/lib/sidekiq/web/helpers.rb +104 -33
  47. data/lib/sidekiq/web.rb +63 -2
  48. data/lib/sidekiq.rb +2 -1
  49. data/sidekiq.gemspec +8 -29
  50. data/web/assets/javascripts/application.js +45 -0
  51. data/web/assets/javascripts/dashboard-charts.js +38 -12
  52. data/web/assets/javascripts/dashboard.js +8 -10
  53. data/web/assets/javascripts/metrics.js +64 -2
  54. data/web/assets/stylesheets/application-dark.css +4 -0
  55. data/web/assets/stylesheets/application-rtl.css +10 -0
  56. data/web/assets/stylesheets/application.css +38 -4
  57. data/web/locales/da.yml +11 -4
  58. data/web/locales/en.yml +2 -0
  59. data/web/locales/fr.yml +14 -0
  60. data/web/locales/gd.yml +99 -0
  61. data/web/locales/ja.yml +3 -1
  62. data/web/locales/pt-br.yml +20 -0
  63. data/web/locales/tr.yml +101 -0
  64. data/web/locales/zh-cn.yml +20 -19
  65. data/web/views/_footer.erb +14 -2
  66. data/web/views/_job_info.erb +18 -2
  67. data/web/views/_metrics_period_select.erb +12 -0
  68. data/web/views/_paging.erb +2 -0
  69. data/web/views/_poll_link.erb +1 -1
  70. data/web/views/_summary.erb +7 -7
  71. data/web/views/busy.erb +46 -35
  72. data/web/views/dashboard.erb +25 -35
  73. data/web/views/filtering.erb +7 -0
  74. data/web/views/layout.erb +6 -6
  75. data/web/views/metrics.erb +42 -31
  76. data/web/views/metrics_for_job.erb +41 -51
  77. data/web/views/morgue.erb +5 -9
  78. data/web/views/queue.erb +10 -14
  79. data/web/views/queues.erb +9 -3
  80. data/web/views/retries.erb +5 -9
  81. data/web/views/scheduled.erb +12 -13
  82. metadata +37 -32
@@ -12,10 +12,22 @@
12
12
  <p id="serverUtcTime" class="navbar-text server-utc-time"><%= server_utc_time %></p>
13
13
  </li>
14
14
  <li>
15
- <p class="navbar-text"><a rel=help href="https://github.com/mperham/sidekiq/wiki">docs</a></p>
15
+ <p class="navbar-text"><a rel=help href="https://github.com/sidekiq/sidekiq/wiki">docs</a></p>
16
16
  </li>
17
17
  <li>
18
- <p class="navbar-text"><a rel=external href="https://github.com/mperham/sidekiq/tree/main/web/locales"><%= locale %></a></p>
18
+ <form id="locale-form" class="form-inline" action="<%= root_path %>change_locale" method="post">
19
+ <%= csrf_tag %>
20
+ <label class="sr-only" for="locale">Language</label>
21
+ <select id="locale-select" class="form-control" name="locale">
22
+ <% available_locales.each do |locale_option| %>
23
+ <% if locale_option == locale %>
24
+ <option selected value="<%= locale_option %>"><%= locale_option %></option>
25
+ <% else %>
26
+ <option value="<%= locale_option %>"><%= locale_option %></option>
27
+ <% end %>
28
+ <% end %>
29
+ </select>
30
+ </form>
19
31
  </li>
20
32
  </ul>
21
33
  </div>
@@ -1,6 +1,6 @@
1
- <header>
1
+ <div class="header-container">
2
2
  <h3><%= t('Job') %></h3>
3
- </header>
3
+ </div>
4
4
 
5
5
  <div class="table_container">
6
6
  <table class="table table-bordered table-striped table-hover">
@@ -33,6 +33,14 @@
33
33
  <code><%= job.jid %></code>
34
34
  </td>
35
35
  </tr>
36
+ <% if job.bid %>
37
+ <tr>
38
+ <th>BID</th>
39
+ <td>
40
+ <a href="<%= root_path %>batches/<%= job.bid %>"><%= job.bid %></a>
41
+ </td>
42
+ </tr>
43
+ <% end %>
36
44
  <tr>
37
45
  <th><%= t('CreatedAt') %></th>
38
46
  <td><%= relative_time(job.created_at) %></td>
@@ -84,6 +92,14 @@
84
92
  <td><%= relative_time(job.at) if job['retry_count'] %></td>
85
93
  </tr>
86
94
  <% end %>
95
+ <% Sidekiq::Web.custom_job_info_rows.each do |helper| %>
96
+ <% helper.add_pair(job) do |name, value| %>
97
+ <tr>
98
+ <th><%= name %></th>
99
+ <td><%= value %></td>
100
+ </tr>
101
+ <% end %>
102
+ <% end %>
87
103
  </tbody>
88
104
  </table>
89
105
  </div>
@@ -0,0 +1,12 @@
1
+ <div>
2
+ <select class="form-control" data-metric-period="<%= path %>">
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>
@@ -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,4 +1,4 @@
1
- <% if current_path != '' %>
1
+ <% if pollable? %>
2
2
  <a class="live-poll-start live-poll btn btn-primary"><%= t('LivePoll') %></a>
3
3
  <a class="live-poll-stop live-poll btn btn-primary active"><%= t('StopPolling') %></a>
4
4
  <% end %>
@@ -1,39 +1,39 @@
1
1
  <ul class="list-unstyled summary row">
2
2
  <li class="processed col-sm-1">
3
- <span id="txtProcessed" class="count"><%= number_with_delimiter(stats.processed) %></span>
3
+ <span id="txtProcessed" class="count" data-nwp><%= stats.processed %></span>
4
4
  <span class="desc"><%= t('Processed') %></span>
5
5
  </li>
6
6
  <li class="failed col-sm-1">
7
- <span id="txtFailed" class="count"><%= number_with_delimiter(stats.failed) %></span>
7
+ <span id="txtFailed" class="count" data-nwp><%= 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 id="txtBusy" class="count"><%= number_with_delimiter(workset.size) %></span>
12
+ <span id="txtBusy" class="count" data-nwp><%= 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 id="txtEnqueued" class="count"><%= number_with_delimiter(stats.enqueued) %></span>
18
+ <span id="txtEnqueued" class="count" data-nwp><%= 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 id="txtRetries" class="count"><%= number_with_delimiter(stats.retry_size) %></span>
24
+ <span id="txtRetries" class="count" data-nwp><%= 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 id="txtScheduled" class="count"><%= number_with_delimiter(stats.scheduled_size) %></span>
30
+ <span id="txtScheduled" class="count" data-nwp><%= 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 id="txtDead" class="count"><%= number_with_delimiter(stats.dead_size) %></span>
36
+ <span id="txtDead" class="count" data-nwp><%= 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">
@@ -29,26 +27,25 @@
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 target="blank" 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>
@@ -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,36 +70,47 @@
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
- <td><%= format_memory(process['rss'].to_i) %></td>
77
- <td><%= process['concurrency'] %></td>
78
- <td><%= process['busy'] %></td>
89
+ <td class="num"><%= format_memory(process['rss'].to_i) %></td>
90
+ <td class="num"><%= number_with_delimiter(process['concurrency']) %></td>
91
+ <td class="num"><%= number_with_delimiter(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>
99
112
  <% if @workset.size > 0 && @total_size > @count %>
100
- <div class="col-sm-4">
101
- <%= erb :_paging, locals: { url: "#{root_path}busy" } %>
102
- </div>
113
+ <%= erb :_paging, locals: { url: "#{root_path}busy" } %>
103
114
  <% end %>
104
115
  </div>
105
116
 
@@ -114,14 +125,14 @@
114
125
  <th><%= t('Arguments') %></th>
115
126
  <th><%= t('Started') %></th>
116
127
  </thead>
117
- <% @workset.each do |process, thread, msg| %>
118
- <% job = Sidekiq::JobRecord.new(msg['payload']) %>
128
+ <% @workset.each do |process, thread, work| %>
129
+ <% job = work.job %>
119
130
  <tr>
120
131
  <td><%= process %></td>
121
132
  <td><%= thread %></td>
122
133
  <td><%= job.jid %></td>
123
134
  <td>
124
- <a href="<%= root_path %>queues/<%= msg['queue'] %>"><%= msg['queue'] %></a>
135
+ <a href="<%= root_path %>queues/<%= work.queue %>"><%= work.queue %></a>
125
136
  </td>
126
137
  <td>
127
138
  <%= job.display_class %>
@@ -130,7 +141,7 @@
130
141
  <td>
131
142
  <div class="args"><%= display_args(job.display_args) %></div>
132
143
  </td>
133
- <td><%= relative_time(Time.at(msg['run_at'])) %></td>
144
+ <td><%= relative_time(work.run_at) %></td>
134
145
  </tr>
135
146
  <% end %>
136
147
  </table>
@@ -1,8 +1,4 @@
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>
5
- <script type="text/javascript" src="<%= root_path %>javascripts/dashboard.js"></script>
1
+ <script type="text/javascript" src="<%= root_path %>javascripts/dashboard.js" nonce="<%= csp_nonce %>"></script>
6
2
  <div class= "dashboard clearfix">
7
3
  <h3 >
8
4
  <%= t('Dashboard') %>
@@ -13,33 +9,26 @@
13
9
  </h3>
14
10
  <div class="interval-slider ltr">
15
11
  <span class="interval-slider-label"><%= t('PollingInterval') %>:</span>
16
- <span id="sldr-text" class="current-interval">5 sec</span>
12
+ <span id="sldr-text" class="current-interval">5 s</span>
17
13
  <br/>
18
14
  <input id="sldr" type="range" min="2000" max="20000" step="1000" value="5000"/>
19
15
  </div>
20
16
  </div>
21
17
 
22
18
  <div class="row chart">
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>
19
+ <canvas id="realtime-chart">
20
+ <%= to_json({
21
+ processedLabel: t('Processed'),
22
+ failedLabel: t('Failed'),
23
+ labels: Array.new(50, ""),
24
+ processed: Array.new(50),
25
+ failed: Array.new(50),
26
+ updateUrl: "#{root_path}stats",
27
+ }) %>
28
+ </canvas>
37
29
 
38
30
  <!-- start with a space in the legend so the height doesn't change when we add content dynamically -->
39
31
  <div id="realtime-legend">&nbsp;</div>
40
- <script>
41
- realtimeChart.registerLegend(document.getElementById("realtime-legend"))
42
- </script>
43
32
  </div>
44
33
 
45
34
  <div class="row header">
@@ -55,18 +44,14 @@
55
44
  <a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
56
45
  </div>
57
46
 
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>
47
+ <canvas id="history-chart">
48
+ <%= to_json({
49
+ processedLabel: t('Processed'),
50
+ failedLabel: t('Failed'),
51
+ processed: @processed_history.to_a.reverse,
52
+ failed: @failed_history.to_a.reverse,
53
+ }) %>
54
+ </canvas>
70
55
  </div>
71
56
 
72
57
  <br/>
@@ -113,3 +98,8 @@
113
98
  <% end %>
114
99
  </div>
115
100
  </div>
101
+
102
+ <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js" nonce="<%= csp_nonce %>"></script>
103
+ <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js" nonce="<%= csp_nonce %>"></script>
104
+ <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js" nonce="<%= csp_nonce %>"></script>
105
+ <script type="text/javascript" src="<%= root_path %>javascripts/dashboard-charts.js" nonce="<%= csp_nonce %>"></script>
@@ -0,0 +1,7 @@
1
+ <div>
2
+ <form method="post" class="form-inline" action='<%= root_path %>filter/<%= which %>'>
3
+ <%= csrf_tag %>
4
+ <label for="substr"><%= t('Filter') %></label>
5
+ <input class="search form-control" type="search" name="substr" value="<%= h params[:substr] %>" placeholder="<%= t('AnyJobContent') %>"/>
6
+ </form>
7
+ </div>
data/web/views/layout.erb CHANGED
@@ -5,20 +5,20 @@
5
5
  <meta charset="utf-8" />
6
6
  <meta name="viewport" content="width=device-width,initial-scale=1.0" />
7
7
 
8
- <link href="<%= root_path %>stylesheets/bootstrap.css" media="screen" rel="stylesheet" type="text/css" />
8
+ <link href="<%= root_path %>stylesheets/bootstrap.css" media="screen" rel="stylesheet" type="text/css" nonce="<%= csp_nonce %>" />
9
9
  <% if rtl? %>
10
- <link href="<%= root_path %>stylesheets/bootstrap-rtl.min.css" media="screen" rel="stylesheet" type="text/css"/>
10
+ <link href="<%= root_path %>stylesheets/bootstrap-rtl.min.css" media="screen" rel="stylesheet" type="text/css" nonce="<%= csp_nonce %>"/>
11
11
  <% end %>
12
12
 
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" />
13
+ <link href="<%= root_path %>stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" nonce="<%= csp_nonce %>" />
14
+ <link href="<%= root_path %>stylesheets/application-dark.css" media="screen and (prefers-color-scheme: dark)" rel="stylesheet" type="text/css" nonce="<%= csp_nonce %>" />
15
15
  <% if rtl? %>
16
- <link href="<%= root_path %>stylesheets/application-rtl.css" media="screen" rel="stylesheet" type="text/css" />
16
+ <link href="<%= root_path %>stylesheets/application-rtl.css" media="screen" rel="stylesheet" type="text/css" nonce="<%= csp_nonce %>" />
17
17
  <% end %>
18
18
 
19
19
  <link rel="apple-touch-icon" href="<%= root_path %>images/apple-touch-icon.png">
20
20
  <link rel="shortcut icon" type="image/ico" href="<%= root_path %>images/favicon.ico" />
21
- <script type="text/javascript" src="<%= root_path %>javascripts/application.js"></script>
21
+ <script type="text/javascript" src="<%= root_path %>javascripts/application.js" nonce="<%= csp_nonce %>"></script>
22
22
  <meta name="google" content="notranslate" />
23
23
  <%= display_custom_head %>
24
24
  </head>
@@ -1,13 +1,28 @@
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>
1
+ <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js" nonce="<%= csp_nonce %>"></script>
2
+ <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js" nonce="<%= csp_nonce %>"></script>
3
+ <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js" nonce="<%= csp_nonce %>"></script>
5
4
 
6
5
  <div class="header-container">
7
- <h1><%= t('Metrics') %></h1>
6
+ <div class="page-title-container">
7
+ <h1><%= t('Metrics') %></h1>
8
+ <a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Metrics"><span class="info-circle" title="Click to learn more about metrics">?</span></a>
9
+ </div>
8
10
 
9
11
  <div>
10
- <a target="blank" href="https://github.com/mperham/sidekiq/wiki/Metrics"><span class="info-circle" title="Click to learn more about metrics">?</span></a>
12
+ <form id="metrics-form" class="form-inline" action="<%= root_path %>filter/metrics" method="post">
13
+ <%= csrf_tag %>
14
+ <label for="substr"><%= t('Filter') %></label>
15
+ <input id="class-filter" class="form-control" type="text" name="substr" placeholder="<%= t('Name') %>" value="<%= h params[:substr] %>">
16
+ <select id="period-selector" class="form-control" name="period">
17
+ <% @periods.each_key do |code| %>
18
+ <% if code == @period %>
19
+ <option selected value="<%= code %>"><%= code %></option>
20
+ <% else %>
21
+ <option value="<%= code %>"><%= code %></option>
22
+ <% end %>
23
+ <% end %>
24
+ </select>
25
+ </form>
11
26
  </div>
12
27
  </div>
13
28
 
@@ -19,22 +34,17 @@
19
34
  %>
20
35
 
21
36
  <% if job_results.any? %>
22
- <canvas id="job-metrics-overview-chart"></canvas>
23
-
24
- <script>
25
- window.jobMetricsChart = new JobMetricsOverviewChart(
26
- document.getElementById("job-metrics-overview-chart"),
27
- <%= Sidekiq.dump_json({
28
- series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
29
- marks: @query_result.marks.map { |m| [m.bucket, m.label] },
30
- labels: @query_result.buckets,
31
- visibleKls: visible_kls,
32
- yLabel: t('TotalExecutionTime'),
33
- units: t('Seconds').downcase,
34
- markLabel: t('Deploy'),
35
- }) %>
36
- )
37
- </script>
37
+ <canvas id="job-metrics-overview-chart">
38
+ <%= to_json({
39
+ series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
40
+ marks: @query_result.marks.map { |m| [m.bucket, m.label] },
41
+ labels: @query_result.buckets,
42
+ visibleKls: visible_kls,
43
+ yLabel: t('TotalExecutionTime'),
44
+ units: t('Seconds').downcase,
45
+ markLabel: t('Deploy'),
46
+ }) %>
47
+ </canvas>
38
48
  <% end %>
39
49
 
40
50
  <div class="table_container">
@@ -44,8 +54,8 @@
44
54
  <th><%= t('Name') %></th>
45
55
  <th><%= t('Success') %></th>
46
56
  <th><%= t('Failure') %></th>
47
- <th><%= t('TotalExecutionTime') %></th>
48
- <th><%= t('AvgExecutionTime') %></th>
57
+ <th><%= t('TotalExecutionTime') %> (Seconds)</th>
58
+ <th><%= t('AvgExecutionTime') %> (Seconds)</th>
49
59
  </tr>
50
60
  <% if job_results.any? %>
51
61
  <% job_results.each_with_index do |(kls, jr), i| %>
@@ -60,14 +70,13 @@
60
70
  value="<%= kls %>"
61
71
  <%= visible_kls.include?(kls) ? 'checked' : '' %>
62
72
  />
63
- <code><a href="<%= root_path %>metrics/<%= kls %>"><%= kls %></a></code>
73
+ <code><a href="<%= root_path %>metrics/<%= kls %>?period=<%= @period %>"><%= kls %></a></code>
64
74
  </div>
65
- <script>jobMetricsChart.registerSwatch("<%= id %>")</script>
66
75
  </td>
67
- <td><%= jr.dig("totals", "p") - jr.dig("totals", "f") %></td>
68
- <td><%= jr.dig("totals", "f") %></td>
69
- <td><%= jr.dig("totals", "s").round(2) %> seconds</td>
70
- <td><%= jr.total_avg("s").round(2) %> seconds</td>
76
+ <td class="num"><%= number_with_delimiter(jr.dig("totals", "p") - jr.dig("totals", "f")) %></td>
77
+ <td class="num"><%= number_with_delimiter(jr.dig("totals", "f")) %></td>
78
+ <td class="num"><%= number_with_delimiter(jr.dig("totals", "s"), precision: 2) %></td>
79
+ <td class="num"><%= number_with_delimiter(jr.total_avg("s"), precision: 2) %></td>
71
80
  </tr>
72
81
  <% end %>
73
82
  <% else %>
@@ -77,4 +86,6 @@
77
86
  </table>
78
87
  </div>
79
88
 
80
- <p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
89
+ <!--p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p-->
90
+
91
+ <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js" nonce="<%= csp_nonce %>"></script>