sidekiq 6.5.10 → 8.1.7
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.
- checksums.yaml +4 -4
- data/Changes.md +568 -18
- data/README.md +66 -38
- data/bin/kiq +17 -0
- data/bin/lint-herb +13 -0
- data/bin/multi_queue_bench +271 -0
- data/bin/sidekiq +3 -8
- data/bin/sidekiqload +215 -118
- data/bin/sidekiqmon +3 -0
- data/bin/webload +69 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +124 -0
- data/lib/generators/sidekiq/job_generator.rb +17 -3
- data/lib/generators/sidekiq/templates/job.rb.erb +1 -1
- data/lib/sidekiq/api.rb +526 -218
- data/lib/sidekiq/capsule.rb +135 -0
- data/lib/sidekiq/cli.rb +88 -96
- data/lib/sidekiq/client.rb +114 -47
- data/lib/sidekiq/component.rb +71 -4
- data/lib/sidekiq/config.rb +316 -0
- data/lib/sidekiq/deploy.rb +64 -0
- data/lib/sidekiq/embedded.rb +64 -0
- data/lib/sidekiq/fetch.rb +12 -14
- data/lib/sidekiq/iterable_job.rb +56 -0
- data/lib/sidekiq/job/interrupt_handler.rb +24 -0
- data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
- data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
- data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
- data/lib/sidekiq/job/iterable.rb +322 -0
- data/lib/sidekiq/job.rb +397 -10
- data/lib/sidekiq/job_logger.rb +14 -11
- data/lib/sidekiq/job_retry.rb +78 -28
- data/lib/sidekiq/job_util.rb +58 -16
- data/lib/sidekiq/launcher.rb +86 -70
- data/lib/sidekiq/loader.rb +57 -0
- data/lib/sidekiq/logger.rb +25 -94
- data/lib/sidekiq/manager.rb +11 -13
- data/lib/sidekiq/metrics/query.rb +84 -48
- data/lib/sidekiq/metrics/shared.rb +29 -14
- data/lib/sidekiq/metrics/tracking.rb +49 -30
- data/lib/sidekiq/middleware/chain.rb +19 -18
- data/lib/sidekiq/middleware/current_attributes.rb +78 -21
- data/lib/sidekiq/middleware/i18n.rb +2 -0
- data/lib/sidekiq/middleware/modules.rb +2 -0
- data/lib/sidekiq/monitor.rb +15 -5
- data/lib/sidekiq/paginator.rb +26 -4
- data/lib/sidekiq/processor.rb +78 -65
- data/lib/sidekiq/profiler.rb +73 -0
- data/lib/sidekiq/rails.rb +45 -60
- data/lib/sidekiq/redis_client_adapter.rb +35 -72
- data/lib/sidekiq/redis_connection.rb +54 -114
- data/lib/sidekiq/ring_buffer.rb +3 -0
- data/lib/sidekiq/scheduled.rb +28 -30
- data/lib/sidekiq/systemd.rb +2 -0
- data/lib/sidekiq/test_api.rb +331 -0
- data/lib/sidekiq/testing/inline.rb +2 -30
- data/lib/sidekiq/testing.rb +2 -342
- data/lib/sidekiq/transaction_aware_client.rb +23 -9
- data/lib/sidekiq/tui/controls.rb +53 -0
- data/lib/sidekiq/tui/filtering.rb +53 -0
- data/lib/sidekiq/tui/tabs/base_tab.rb +230 -0
- data/lib/sidekiq/tui/tabs/busy.rb +104 -0
- data/lib/sidekiq/tui/tabs/dead.rb +14 -0
- data/lib/sidekiq/tui/tabs/home.rb +115 -0
- data/lib/sidekiq/tui/tabs/metrics.rb +114 -0
- data/lib/sidekiq/tui/tabs/queues.rb +83 -0
- data/lib/sidekiq/tui/tabs/retries.rb +14 -0
- data/lib/sidekiq/tui/tabs/scheduled.rb +14 -0
- data/lib/sidekiq/tui/tabs/set_tab.rb +91 -0
- data/lib/sidekiq/tui/tabs.rb +15 -0
- data/lib/sidekiq/tui.rb +390 -0
- data/lib/sidekiq/version.rb +6 -1
- data/lib/sidekiq/web/action.rb +149 -64
- data/lib/sidekiq/web/application.rb +379 -281
- data/lib/sidekiq/web/config.rb +117 -0
- data/lib/sidekiq/web/helpers.rb +190 -71
- data/lib/sidekiq/web/router.rb +62 -75
- data/lib/sidekiq/web.rb +68 -101
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +85 -269
- data/sidekiq.gemspec +15 -11
- data/web/assets/images/logo.png +0 -0
- data/web/assets/images/status.png +0 -0
- data/web/assets/javascripts/application.js +84 -24
- data/web/assets/javascripts/base-charts.js +120 -0
- data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
- data/web/assets/javascripts/dashboard-charts.js +194 -0
- data/web/assets/javascripts/dashboard.js +18 -234
- data/web/assets/javascripts/metrics.js +138 -120
- data/web/assets/stylesheets/style.css +776 -0
- data/web/locales/ar.yml +72 -70
- data/web/locales/cs.yml +64 -62
- data/web/locales/da.yml +62 -53
- data/web/locales/de.yml +67 -65
- data/web/locales/el.yml +4 -7
- data/web/locales/en.yml +89 -71
- data/web/locales/es.yml +91 -68
- data/web/locales/fa.yml +67 -65
- data/web/locales/fr.yml +82 -67
- data/web/locales/gd.yml +110 -0
- data/web/locales/he.yml +67 -64
- data/web/locales/hi.yml +95 -59
- data/web/locales/it.yml +94 -54
- data/web/locales/ja.yml +69 -70
- data/web/locales/ko.yml +54 -52
- data/web/locales/lt.yml +68 -66
- data/web/locales/nb.yml +63 -61
- data/web/locales/nl.yml +54 -52
- data/web/locales/pl.yml +47 -45
- data/web/locales/{pt-br.yml → pt-BR.yml} +81 -70
- data/web/locales/pt.yml +53 -51
- data/web/locales/ru.yml +69 -66
- data/web/locales/sv.yml +55 -53
- data/web/locales/ta.yml +100 -64
- data/web/locales/tr.yml +102 -0
- data/web/locales/uk.yml +87 -61
- data/web/locales/ur.yml +66 -64
- data/web/locales/vi.yml +69 -67
- data/web/locales/zh-CN.yml +107 -0
- data/web/locales/{zh-tw.yml → zh-TW.yml} +13 -3
- data/web/views/_footer.html.erb +32 -0
- data/web/views/_job_info.html.erb +115 -0
- data/web/views/_metrics_period_select.html.erb +15 -0
- data/web/views/_nav.html.erb +45 -0
- data/web/views/_paging.html.erb +26 -0
- data/web/views/_poll_link.html.erb +4 -0
- data/web/views/_summary.html.erb +40 -0
- data/web/views/busy.html.erb +155 -0
- data/web/views/dashboard.html.erb +104 -0
- data/web/views/dead.html.erb +38 -0
- data/web/views/filtering.html.erb +6 -0
- data/web/views/layout.html.erb +26 -0
- data/web/views/metrics.html.erb +85 -0
- data/web/views/metrics_for_job.html.erb +58 -0
- data/web/views/morgue.html.erb +69 -0
- data/web/views/profiles.html.erb +43 -0
- data/web/views/queue.html.erb +57 -0
- data/web/views/queues.html.erb +46 -0
- data/web/views/retries.html.erb +77 -0
- data/web/views/retry.html.erb +39 -0
- data/web/views/scheduled.html.erb +64 -0
- data/web/views/{scheduled_job_info.erb → scheduled_job_info.html.erb} +3 -3
- metadata +113 -70
- data/lib/sidekiq/delay.rb +0 -43
- data/lib/sidekiq/extensions/action_mailer.rb +0 -48
- data/lib/sidekiq/extensions/active_record.rb +0 -43
- data/lib/sidekiq/extensions/class_methods.rb +0 -43
- data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
- data/lib/sidekiq/metrics/deploy.rb +0 -47
- data/lib/sidekiq/web/csrf_protection.rb +0 -180
- data/lib/sidekiq/worker.rb +0 -370
- data/web/assets/javascripts/graph.js +0 -16
- data/web/assets/stylesheets/application-dark.css +0 -143
- data/web/assets/stylesheets/application-rtl.css +0 -242
- data/web/assets/stylesheets/application.css +0 -999
- data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
- data/web/assets/stylesheets/bootstrap.css +0 -5
- data/web/locales/zh-cn.yml +0 -93
- data/web/views/_footer.erb +0 -20
- data/web/views/_job_info.erb +0 -89
- data/web/views/_nav.erb +0 -52
- data/web/views/_paging.erb +0 -23
- data/web/views/_poll_link.erb +0 -4
- data/web/views/_status.erb +0 -4
- data/web/views/_summary.erb +0 -40
- data/web/views/busy.erb +0 -137
- data/web/views/dashboard.erb +0 -84
- data/web/views/dead.erb +0 -34
- data/web/views/layout.erb +0 -42
- data/web/views/metrics.erb +0 -69
- data/web/views/metrics_for_job.erb +0 -87
- data/web/views/morgue.erb +0 -78
- data/web/views/queue.erb +0 -59
- data/web/views/queues.erb +0 -38
- data/web/views/retries.erb +0 -83
- data/web/views/retry.erb +0 -34
- data/web/views/scheduled.erb +0 -57
- /data/{LICENSE → LICENSE.txt} +0 -0
|
@@ -1,89 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class BaseChart {
|
|
7
|
-
constructor(id, options) {
|
|
8
|
-
this.ctx = document.getElementById(id);
|
|
9
|
-
this.options = options
|
|
10
|
-
this.fallbackColor = "#999";
|
|
11
|
-
this.colors = [
|
|
12
|
-
// Colors taken from https://www.chartjs.org/docs/latest/samples/utils.html
|
|
13
|
-
"#537bc4",
|
|
14
|
-
"#4dc9f6",
|
|
15
|
-
"#f67019",
|
|
16
|
-
"#f53794",
|
|
17
|
-
"#acc236",
|
|
18
|
-
"#166a8f",
|
|
19
|
-
"#00a950",
|
|
20
|
-
"#58595b",
|
|
21
|
-
"#8549ba",
|
|
22
|
-
"#991b1b",
|
|
23
|
-
];
|
|
1
|
+
class JobMetricsOverviewChart extends BaseChart {
|
|
2
|
+
constructor(el, options) {
|
|
3
|
+
super(el, { ...options, chartType: "line" });
|
|
4
|
+
this.swatches = [];
|
|
5
|
+
this.visibleKls = options.visibleKls;
|
|
24
6
|
|
|
25
|
-
this.
|
|
26
|
-
type: this.options.chartType,
|
|
27
|
-
data: { labels: this.options.labels, datasets: this.datasets },
|
|
28
|
-
options: this.chartOptions,
|
|
29
|
-
});
|
|
7
|
+
this.init();
|
|
30
8
|
}
|
|
31
9
|
|
|
32
|
-
|
|
33
|
-
this.options.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
xMin: bucket,
|
|
37
|
-
xMax: bucket,
|
|
38
|
-
borderColor: "rgba(220, 38, 38, 0.4)",
|
|
39
|
-
borderWidth: 2,
|
|
40
|
-
};
|
|
41
|
-
});
|
|
10
|
+
get datasets() {
|
|
11
|
+
return Object.entries(this.options.series)
|
|
12
|
+
.filter(([kls, _]) => this.visibleKls.includes(kls))
|
|
13
|
+
.map(([kls, _]) => this.buildDataset(kls));
|
|
42
14
|
}
|
|
43
|
-
}
|
|
44
15
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.swatches = [];
|
|
16
|
+
get metric() {
|
|
17
|
+
return this._metric || this.options.initialMetric;
|
|
18
|
+
}
|
|
49
19
|
|
|
50
|
-
|
|
51
|
-
this.
|
|
20
|
+
set metric(m) {
|
|
21
|
+
this._metric = m;
|
|
52
22
|
}
|
|
53
23
|
|
|
54
24
|
registerSwatch(id) {
|
|
55
25
|
const el = document.getElementById(id);
|
|
56
|
-
el.
|
|
26
|
+
el.addEventListener("change", () => this.toggleKls(el.value, el.checked));
|
|
57
27
|
this.swatches[el.value] = el;
|
|
58
|
-
this.updateSwatch(el.value);
|
|
28
|
+
this.updateSwatch(el.value, el.checked);
|
|
59
29
|
}
|
|
60
30
|
|
|
61
|
-
updateSwatch(kls) {
|
|
31
|
+
updateSwatch(kls, checked) {
|
|
62
32
|
const el = this.swatches[kls];
|
|
63
|
-
|
|
64
|
-
el.
|
|
65
|
-
el.style.color = ds ? ds.borderColor : null;
|
|
33
|
+
el.checked = checked;
|
|
34
|
+
el.style.accentColor = this.colors.assignments[kls] || "";
|
|
66
35
|
}
|
|
67
36
|
|
|
68
|
-
|
|
37
|
+
toggleKls(kls, visible) {
|
|
69
38
|
if (visible) {
|
|
70
|
-
this.chart.data.datasets.push(this.
|
|
39
|
+
this.chart.data.datasets.push(this.buildDataset(kls));
|
|
71
40
|
} else {
|
|
72
41
|
const i = this.chart.data.datasets.findIndex((ds) => ds.label == kls);
|
|
73
|
-
this.colors.
|
|
42
|
+
this.colors.checkIn(kls);
|
|
74
43
|
this.chart.data.datasets.splice(i, 1);
|
|
75
44
|
}
|
|
76
45
|
|
|
77
|
-
this.updateSwatch(kls);
|
|
78
|
-
this.
|
|
46
|
+
this.updateSwatch(kls, visible);
|
|
47
|
+
this.update();
|
|
79
48
|
}
|
|
80
49
|
|
|
81
|
-
|
|
82
|
-
const color = this.colors.
|
|
50
|
+
buildDataset(kls) {
|
|
51
|
+
const color = this.colors.checkOut(kls);
|
|
83
52
|
|
|
84
53
|
return {
|
|
85
54
|
label: kls,
|
|
86
|
-
data: this.options.series[kls],
|
|
55
|
+
data: this.dataFromSeries(this.options.series[kls]),
|
|
87
56
|
borderColor: color,
|
|
88
57
|
backgroundColor: color,
|
|
89
58
|
borderWidth: 2,
|
|
@@ -91,40 +60,46 @@ class JobMetricsOverviewChart extends BaseChart {
|
|
|
91
60
|
};
|
|
92
61
|
}
|
|
93
62
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.map(([kls, _]) => this.dataset(kls));
|
|
63
|
+
dataFromSeries(series) {
|
|
64
|
+
// Chart.js expects `data` to be an array of objects with `x` and `y` values.
|
|
65
|
+
return Object.entries(series).map(([isoTime, val]) => ({ x: isoTime, y: val }));
|
|
98
66
|
}
|
|
99
67
|
|
|
100
68
|
get chartOptions() {
|
|
101
69
|
return {
|
|
70
|
+
...super.chartOptions,
|
|
102
71
|
aspectRatio: 4,
|
|
103
72
|
scales: {
|
|
73
|
+
...super.chartOptions.scales,
|
|
74
|
+
x: {
|
|
75
|
+
...super.chartOptions.scales.x,
|
|
76
|
+
type: "time",
|
|
77
|
+
min: this.options.starts_at,
|
|
78
|
+
max: this.options.ends_at,
|
|
79
|
+
},
|
|
104
80
|
y: {
|
|
81
|
+
...super.chartOptions.scales.y,
|
|
105
82
|
beginAtZero: true,
|
|
106
83
|
title: {
|
|
107
|
-
text:
|
|
84
|
+
text: this.options.yLabel,
|
|
108
85
|
display: true,
|
|
109
86
|
},
|
|
110
87
|
},
|
|
111
88
|
},
|
|
112
|
-
interaction: {
|
|
113
|
-
mode: "x",
|
|
114
|
-
},
|
|
115
89
|
plugins: {
|
|
116
|
-
|
|
117
|
-
display: false,
|
|
118
|
-
},
|
|
90
|
+
...super.chartOptions.plugins,
|
|
119
91
|
tooltip: {
|
|
92
|
+
...super.chartOptions.plugins.tooltip,
|
|
120
93
|
callbacks: {
|
|
121
|
-
title: (items) => `${items[0].label} UTC`,
|
|
122
94
|
label: (item) =>
|
|
123
|
-
`${item.dataset.label}: ${item.parsed.y.toFixed(1)}
|
|
95
|
+
`${item.dataset.label}: ${item.parsed.y.toFixed(1)} ` +
|
|
96
|
+
`${this.options.units}`,
|
|
124
97
|
footer: (items) => {
|
|
125
|
-
const bucket = items[0].
|
|
98
|
+
const bucket = items[0].raw.x;
|
|
126
99
|
const marks = this.options.marks.filter(([b, _]) => b == bucket);
|
|
127
|
-
return marks.map(
|
|
100
|
+
return marks.map(
|
|
101
|
+
([b, msg]) => `${this.options.markLabel}: ${msg}`
|
|
102
|
+
);
|
|
128
103
|
},
|
|
129
104
|
},
|
|
130
105
|
},
|
|
@@ -134,40 +109,49 @@ class JobMetricsOverviewChart extends BaseChart {
|
|
|
134
109
|
}
|
|
135
110
|
|
|
136
111
|
class HistTotalsChart extends BaseChart {
|
|
137
|
-
constructor(
|
|
138
|
-
super(
|
|
112
|
+
constructor(el, options) {
|
|
113
|
+
super(el, { ...options, chartType: "bar" });
|
|
114
|
+
this.init();
|
|
139
115
|
}
|
|
140
116
|
|
|
141
117
|
get datasets() {
|
|
142
|
-
return [
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
118
|
+
return [
|
|
119
|
+
{
|
|
120
|
+
data: this.options.series,
|
|
121
|
+
backgroundColor: this.colors.primary,
|
|
122
|
+
borderWidth: 0,
|
|
123
|
+
},
|
|
124
|
+
];
|
|
147
125
|
}
|
|
148
126
|
|
|
149
127
|
get chartOptions() {
|
|
150
128
|
return {
|
|
129
|
+
...super.chartOptions,
|
|
151
130
|
aspectRatio: 6,
|
|
152
131
|
scales: {
|
|
132
|
+
...super.chartOptions.scales,
|
|
153
133
|
y: {
|
|
134
|
+
...super.chartOptions.scales.y,
|
|
154
135
|
beginAtZero: true,
|
|
155
136
|
title: {
|
|
156
|
-
text:
|
|
137
|
+
text: this.options.yLabel,
|
|
138
|
+
display: true,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
x: {
|
|
142
|
+
...super.chartOptions.scales.x,
|
|
143
|
+
title: {
|
|
144
|
+
text: this.options.xLabel,
|
|
157
145
|
display: true,
|
|
158
146
|
},
|
|
159
147
|
},
|
|
160
|
-
},
|
|
161
|
-
interaction: {
|
|
162
|
-
mode: "x",
|
|
163
148
|
},
|
|
164
149
|
plugins: {
|
|
165
|
-
|
|
166
|
-
display: false,
|
|
167
|
-
},
|
|
150
|
+
...super.chartOptions.plugins,
|
|
168
151
|
tooltip: {
|
|
152
|
+
...super.chartOptions.plugins.tooltip,
|
|
169
153
|
callbacks: {
|
|
170
|
-
label: (item) => `${item.parsed.y}
|
|
154
|
+
label: (item) => `${item.parsed.y} ${this.options.units}`,
|
|
171
155
|
},
|
|
172
156
|
},
|
|
173
157
|
},
|
|
@@ -176,11 +160,9 @@ class HistTotalsChart extends BaseChart {
|
|
|
176
160
|
}
|
|
177
161
|
|
|
178
162
|
class HistBubbleChart extends BaseChart {
|
|
179
|
-
constructor(
|
|
180
|
-
super(
|
|
181
|
-
|
|
182
|
-
this.addMarksToChart();
|
|
183
|
-
this.chart.update();
|
|
163
|
+
constructor(el, options) {
|
|
164
|
+
super(el, { ...options, chartType: "bubble" });
|
|
165
|
+
this.init();
|
|
184
166
|
}
|
|
185
167
|
|
|
186
168
|
get datasets() {
|
|
@@ -190,13 +172,13 @@ class HistBubbleChart extends BaseChart {
|
|
|
190
172
|
Object.entries(this.options.hist).forEach(([bucket, hist]) => {
|
|
191
173
|
hist.forEach((count, histBucket) => {
|
|
192
174
|
if (count > 0) {
|
|
175
|
+
// histogram data is ordered fastest to slowest, but this.histIntervals is
|
|
176
|
+
// slowest to fastest (so it displays correctly on the chart).
|
|
177
|
+
const index = this.options.histIntervals.length - 1 - histBucket;
|
|
178
|
+
|
|
193
179
|
data.push({
|
|
194
180
|
x: bucket,
|
|
195
|
-
|
|
196
|
-
// slowest to fastest (so it displays correctly on the chart).
|
|
197
|
-
y:
|
|
198
|
-
this.options.histIntervals[this.options.histIntervals.length - 1 - histBucket] /
|
|
199
|
-
1000,
|
|
181
|
+
y: this.options.histIntervals[index] / 1000,
|
|
200
182
|
count: count,
|
|
201
183
|
});
|
|
202
184
|
|
|
@@ -206,53 +188,55 @@ class HistBubbleChart extends BaseChart {
|
|
|
206
188
|
});
|
|
207
189
|
|
|
208
190
|
// Chart.js will not calculate the bubble size. We have to do that.
|
|
209
|
-
const maxRadius = this.
|
|
210
|
-
const minRadius = 1
|
|
191
|
+
const maxRadius = this.el.offsetWidth / 100;
|
|
192
|
+
const minRadius = 1;
|
|
211
193
|
const multiplier = (maxRadius / maxCount) * 1.5;
|
|
212
194
|
data.forEach((entry) => {
|
|
213
195
|
entry.r = entry.count * multiplier + minRadius;
|
|
214
196
|
});
|
|
215
197
|
|
|
216
|
-
return [
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
198
|
+
return [
|
|
199
|
+
{
|
|
200
|
+
data: data,
|
|
201
|
+
backgroundColor: this.colors.primary,
|
|
202
|
+
borderColor: this.colors.primary,
|
|
203
|
+
},
|
|
204
|
+
];
|
|
221
205
|
}
|
|
222
206
|
|
|
223
207
|
get chartOptions() {
|
|
224
208
|
return {
|
|
209
|
+
...super.chartOptions,
|
|
225
210
|
aspectRatio: 3,
|
|
226
211
|
scales: {
|
|
212
|
+
...super.chartOptions.scales,
|
|
227
213
|
x: {
|
|
228
|
-
|
|
229
|
-
|
|
214
|
+
...super.chartOptions.scales.x,
|
|
215
|
+
type: "time",
|
|
216
|
+
min: this.options.starts_at,
|
|
217
|
+
max: this.options.ends_at,
|
|
230
218
|
},
|
|
231
219
|
y: {
|
|
220
|
+
...super.chartOptions.scales.y,
|
|
232
221
|
title: {
|
|
233
|
-
text:
|
|
222
|
+
text: this.options.yLabel,
|
|
234
223
|
display: true,
|
|
235
224
|
},
|
|
236
225
|
},
|
|
237
226
|
},
|
|
238
|
-
interaction: {
|
|
239
|
-
mode: "x",
|
|
240
|
-
},
|
|
241
227
|
plugins: {
|
|
242
|
-
|
|
243
|
-
display: false,
|
|
244
|
-
},
|
|
228
|
+
...super.chartOptions.plugins,
|
|
245
229
|
tooltip: {
|
|
230
|
+
...super.chartOptions.plugins.tooltip,
|
|
246
231
|
callbacks: {
|
|
247
|
-
title: (items) => `${items[0].raw.x} UTC`,
|
|
248
232
|
label: (item) =>
|
|
249
|
-
`${item.parsed.y}
|
|
250
|
-
item.raw.count == 1 ? "" : "s"
|
|
251
|
-
}`,
|
|
233
|
+
`${item.parsed.y} ${this.options.yUnits}: ${item.raw.count} ${this.options.zUnits}`,
|
|
252
234
|
footer: (items) => {
|
|
253
235
|
const bucket = items[0].raw.x;
|
|
254
236
|
const marks = this.options.marks.filter(([b, _]) => b == bucket);
|
|
255
|
-
return marks.map(
|
|
237
|
+
return marks.map(
|
|
238
|
+
([b, msg]) => `${this.options.markLabel}: ${msg}`
|
|
239
|
+
);
|
|
256
240
|
},
|
|
257
241
|
},
|
|
258
242
|
},
|
|
@@ -260,3 +244,37 @@ class HistBubbleChart extends BaseChart {
|
|
|
260
244
|
};
|
|
261
245
|
}
|
|
262
246
|
}
|
|
247
|
+
|
|
248
|
+
var ch = document.getElementById("job-metrics-overview-chart");
|
|
249
|
+
if (ch != null) {
|
|
250
|
+
var jm = new JobMetricsOverviewChart(ch, JSON.parse(ch.textContent));
|
|
251
|
+
document.querySelectorAll(".metrics-swatch-wrapper > input[type=checkbox]").forEach((imp) => {
|
|
252
|
+
jm.registerSwatch(imp.id)
|
|
253
|
+
});
|
|
254
|
+
window.jobMetricsChart = jm;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
var htc = document.getElementById("hist-totals-chart");
|
|
258
|
+
if (htc != null) {
|
|
259
|
+
var tc = new HistTotalsChart(htc, JSON.parse(htc.textContent));
|
|
260
|
+
window.histTotalsChart = tc
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
var hbc = document.getElementById("hist-bubble-chart");
|
|
264
|
+
if (hbc != null) {
|
|
265
|
+
var bc = new HistBubbleChart(hbc, JSON.parse(hbc.textContent));
|
|
266
|
+
window.histBubbleChart = bc
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
var form = document.getElementById("metrics-form")
|
|
270
|
+
document.querySelectorAll("#period-selector").forEach(node => {
|
|
271
|
+
node.addEventListener("input", debounce(() => form.submit()))
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
function debounce(func, timeout = 300) {
|
|
275
|
+
let timer;
|
|
276
|
+
return (...args) => {
|
|
277
|
+
clearTimeout(timer);
|
|
278
|
+
timer = setTimeout(() => { func.apply(this, args); }, timeout);
|
|
279
|
+
};
|
|
280
|
+
}
|