sidekiq_insight 0.1.0 → 0.1.1
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/app/controllers/sidekiq_insight/graphs_controller.rb +11 -5
- data/app/views/layouts/sidekiq_insight/sidekiq_insight.html.erb +2 -0
- data/app/views/sidekiq_insight/dashboard/index.html.erb +41 -25
- data/app/views/sidekiq_insight/graphs/_chart.html.erb +6 -32
- data/app/views/sidekiq_insight/graphs/cpu.html.erb +7 -5
- data/app/views/sidekiq_insight/graphs/leaks.html.erb +2 -3
- data/app/views/sidekiq_insight/graphs/rss.html.erb +11 -17
- data/app/views/sidekiq_insight/graphs/wall.html.erb +13 -6
- data/lib/sidekiq_insight/request_middleware.rb +10 -6
- data/lib/sidekiq_insight/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 930b6bcd68d1c5dc1fde7fcae30c3cb6a3cd2474a97452b5010938ff035a1bd4
|
|
4
|
+
data.tar.gz: e05a5f5fc51daab73546c665440ceee09b501365dabcdcac012a7484436269c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f109133f4a1783e2540881b0f3645303a1dbea628a424a64e65484fa907710e1a5678c3ae336a08336754dcfa9f8e40a9d3614ec3af35b66a9289f29435a9d28
|
|
7
|
+
data.tar.gz: 53c8919b50ae46727fb6873a25c3277190e367c4527982cecb1080ba16706e09c03e6973c710ae82b8d9c163ed16993027d4024e0e1f67f66ede05796229118b
|
|
@@ -26,13 +26,19 @@ module SidekiqInsight
|
|
|
26
26
|
private
|
|
27
27
|
|
|
28
28
|
def build_series(metric_sym)
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
points = []
|
|
30
|
+
|
|
31
|
+
SidekiqInsight.storage.top_jobs(50).each do |job|
|
|
31
32
|
samples = SidekiqInsight.storage.recent(job[:key], 200)
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
samples.each do |s|
|
|
35
|
+
points << [s[:started_at], s[metric_sym].to_f]
|
|
36
|
+
end
|
|
34
37
|
end
|
|
35
|
-
|
|
38
|
+
|
|
39
|
+
points.sort_by! { |t, _| t }
|
|
40
|
+
|
|
41
|
+
points
|
|
36
42
|
end
|
|
37
43
|
end
|
|
38
44
|
end
|
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
<li class="nav-item"><a class="nav-link" href="<%= sidekiq_insight.cpu_path %>">CPU</a></li>
|
|
33
33
|
<li class="nav-item"><a class="nav-link" href="<%= sidekiq_insight.rss_path %>">Memory</a></li>
|
|
34
34
|
<li class="nav-item"><a class="nav-link" href="<%= sidekiq_insight.leaks_path %>">Leak Detector</a></li>
|
|
35
|
+
<li class="nav-item"><a class="nav-link" href="<%= sidekiq_insight.wall_path %>">Wall Time (ms)</a></li>
|
|
36
|
+
|
|
35
37
|
</ul>
|
|
36
38
|
</div>
|
|
37
39
|
</div>
|
|
@@ -6,43 +6,55 @@
|
|
|
6
6
|
<div class="col-md-8">
|
|
7
7
|
<div class="card shadow-sm h-100">
|
|
8
8
|
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
|
9
|
-
<h4 class="mb-0">Top Jobs by Avg CPU</h4>
|
|
10
|
-
<span class="badge bg-light text-primary">
|
|
9
|
+
<h4 class="mb-0"><i class="bi bi-speedometer2"></i> Top Jobs by Avg CPU</h4>
|
|
10
|
+
<span class="badge bg-light text-primary fs-6">
|
|
11
11
|
<%= @jobs.count %> jobs
|
|
12
12
|
</span>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
<div class="card-body p-0">
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
<table class="table table-hover table-striped table-bordered mb-0 align-middle">
|
|
17
18
|
<thead class="table-light">
|
|
18
19
|
<tr>
|
|
19
|
-
<th>Job</th>
|
|
20
|
-
<th>
|
|
21
|
-
<th>Avg CPU
|
|
22
|
-
<th>Avg Mem
|
|
23
|
-
<th
|
|
20
|
+
<th style="width: 40%;">Job</th>
|
|
21
|
+
<th class="text-center" style="width: 10%">Runs</th>
|
|
22
|
+
<th class="text-center" style="width: 15%">Avg CPU</th>
|
|
23
|
+
<th class="text-center" style="width: 15%">Avg Mem</th>
|
|
24
|
+
<th class="text-center" style="width: 10%;">Action</th>
|
|
24
25
|
</tr>
|
|
25
26
|
</thead>
|
|
26
27
|
|
|
27
28
|
<tbody>
|
|
28
29
|
<% @jobs.each do |j| %>
|
|
29
30
|
<tr>
|
|
30
|
-
|
|
31
|
-
<td><%= j[:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
<!-- JOB NAME -->
|
|
32
|
+
<td class="fw-semibold text-break"><%= j[:key] %></td>
|
|
33
|
+
|
|
34
|
+
<!-- RUNS -->
|
|
35
|
+
<td class="text-center">
|
|
36
|
+
<span class="badge bg-secondary"><%= j[:count] %></span>
|
|
37
|
+
</td>
|
|
38
|
+
|
|
39
|
+
<!-- AVG CPU -->
|
|
40
|
+
<td class="text-center">
|
|
41
|
+
<span class="badge bg-info text-dark px-3 py-2">
|
|
42
|
+
<%= number_with_precision(j[:avg_cpu_ms], precision: 2) %> ms
|
|
35
43
|
</span>
|
|
36
44
|
</td>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
|
|
46
|
+
<!-- AVG MEMORY -->
|
|
47
|
+
<td class="text-center">
|
|
48
|
+
<span class="badge bg-success px-3 py-2">
|
|
49
|
+
<%= number_with_precision(j[:avg_mem_kb], precision: 2) %> KB
|
|
40
50
|
</span>
|
|
41
51
|
</td>
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
|
|
53
|
+
<!-- SHOW BUTTON -->
|
|
54
|
+
<td class="text-center">
|
|
55
|
+
<a class="btn btn-sm btn-outline-primary px-3"
|
|
44
56
|
href="<%= sidekiq_insight.job_path(job: j[:key]) %>">
|
|
45
|
-
|
|
57
|
+
Show
|
|
46
58
|
</a>
|
|
47
59
|
</td>
|
|
48
60
|
</tr>
|
|
@@ -54,28 +66,32 @@
|
|
|
54
66
|
</div>
|
|
55
67
|
</div>
|
|
56
68
|
|
|
69
|
+
|
|
57
70
|
<!-- ================= LEAK ALERTS ================= -->
|
|
58
71
|
<div class="col-md-4">
|
|
59
72
|
<div class="card shadow-sm h-100">
|
|
60
|
-
<div class="card-header bg-danger text-white">
|
|
61
|
-
<h4 class="mb-0">Leak Alerts</h4>
|
|
73
|
+
<div class="card-header bg-danger text-white d-flex justify-content-between align-items-center">
|
|
74
|
+
<h4 class="mb-0"><i class="bi bi-exclamation-triangle"></i> Leak Alerts</h4>
|
|
62
75
|
</div>
|
|
63
76
|
|
|
64
77
|
<div class="card-body">
|
|
78
|
+
|
|
65
79
|
<% if @alerts.present? %>
|
|
66
|
-
<ul class="list-group">
|
|
80
|
+
<ul class="list-group shadow-sm">
|
|
67
81
|
<% @alerts.each do |a| %>
|
|
68
82
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
69
83
|
<strong><%= a[:job] %></strong>
|
|
70
|
-
<span class="badge bg-danger"
|
|
84
|
+
<span class="badge bg-danger px-3">⚠ Leak suspected</span>
|
|
71
85
|
</li>
|
|
72
86
|
<% end %>
|
|
73
87
|
</ul>
|
|
74
88
|
<% else %>
|
|
75
|
-
<div class="text-center text-muted py-
|
|
76
|
-
|
|
89
|
+
<div class="text-center text-muted py-4">
|
|
90
|
+
<i class="bi bi-check2-circle fs-1 text-success"></i>
|
|
91
|
+
<div class="mt-2">No recent leak alerts</div>
|
|
77
92
|
</div>
|
|
78
93
|
<% end %>
|
|
94
|
+
|
|
79
95
|
</div>
|
|
80
96
|
</div>
|
|
81
97
|
</div>
|
|
@@ -4,37 +4,11 @@
|
|
|
4
4
|
</div>
|
|
5
5
|
|
|
6
6
|
<div class="card-body">
|
|
7
|
-
|
|
7
|
+
<%= line_chart data,
|
|
8
|
+
height: "260px",
|
|
9
|
+
points: true,
|
|
10
|
+
download: true,
|
|
11
|
+
legend: true,
|
|
12
|
+
curve: true %>
|
|
8
13
|
</div>
|
|
9
14
|
</div>
|
|
10
|
-
|
|
11
|
-
<script>
|
|
12
|
-
document.addEventListener("DOMContentLoaded", function () {
|
|
13
|
-
const ctx = document.getElementById("<%= dom_id %>").getContext("2d");
|
|
14
|
-
|
|
15
|
-
const datasets = [
|
|
16
|
-
<% data.each do |job_key, series| %>
|
|
17
|
-
{
|
|
18
|
-
label: "<%= job_key %>",
|
|
19
|
-
data: <%= series.map { |t, v| { x: t, y: v } }.to_json %>,
|
|
20
|
-
borderWidth: 2,
|
|
21
|
-
tension: 0.3,
|
|
22
|
-
},
|
|
23
|
-
<% end %>
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
new Chart(ctx, {
|
|
27
|
-
type: 'line',
|
|
28
|
-
data: { datasets: datasets },
|
|
29
|
-
options: {
|
|
30
|
-
responsive: true,
|
|
31
|
-
parsing: false,
|
|
32
|
-
plugins: { legend: { position: "bottom" } },
|
|
33
|
-
scales: {
|
|
34
|
-
x: { type: 'time', time: { unit: 'minute' } },
|
|
35
|
-
y: { beginAtZero: true }
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
</script>
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
<h2 class="mb-4 text-primary fw-bold">CPU Usage — Top Jobs</h2>
|
|
3
3
|
|
|
4
4
|
<div class="card mb-4 shadow-sm">
|
|
5
|
-
<div class="card-header bg-dark text-white">
|
|
6
|
-
Job Statistics
|
|
7
|
-
</div>
|
|
5
|
+
<div class="card-header bg-dark text-white">Job Statistics</div>
|
|
8
6
|
|
|
9
7
|
<div class="card-body p-0">
|
|
10
8
|
<table class="table table-striped mb-0">
|
|
@@ -15,6 +13,7 @@
|
|
|
15
13
|
<th>Runs</th>
|
|
16
14
|
</tr>
|
|
17
15
|
</thead>
|
|
16
|
+
|
|
18
17
|
<tbody>
|
|
19
18
|
<% @jobs.each do |job| %>
|
|
20
19
|
<tr>
|
|
@@ -28,6 +27,9 @@
|
|
|
28
27
|
</div>
|
|
29
28
|
</div>
|
|
30
29
|
|
|
31
|
-
<%= render
|
|
32
|
-
|
|
30
|
+
<%= render "chart",
|
|
31
|
+
title: "CPU Time (ms)",
|
|
32
|
+
dom_id: "cpu_chart",
|
|
33
|
+
data: @cpu_chart %>
|
|
33
34
|
</div>
|
|
35
|
+
|
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
</div>
|
|
8
8
|
<% else %>
|
|
9
9
|
<div class="card shadow-sm">
|
|
10
|
-
<div class="card-header bg-danger text-white">
|
|
11
|
-
Leaking Jobs
|
|
12
|
-
</div>
|
|
10
|
+
<div class="card-header bg-danger text-white">Leaking Jobs</div>
|
|
13
11
|
|
|
14
12
|
<div class="card-body p-0">
|
|
15
13
|
<table class="table table-striped mb-0">
|
|
@@ -21,6 +19,7 @@
|
|
|
21
19
|
<th>Runs</th>
|
|
22
20
|
</tr>
|
|
23
21
|
</thead>
|
|
22
|
+
|
|
24
23
|
<tbody>
|
|
25
24
|
<% @leak_jobs.each do |job| %>
|
|
26
25
|
<tr class="table-danger">
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
<div class="container py-4">
|
|
2
|
+
<h2 class="mb-4 text-success fw-bold">RSS Memory Usage — Top Jobs</h2>
|
|
2
3
|
|
|
3
|
-
<h2 class="mb-4 text-success fw-bold">
|
|
4
|
-
RSS Memory Usage — Top Jobs
|
|
5
|
-
</h2>
|
|
6
|
-
|
|
7
|
-
<!-- Jobs Table -->
|
|
8
4
|
<div class="card mb-4 shadow-sm">
|
|
9
|
-
<div class="card-header bg-success text-white">
|
|
10
|
-
Job Memory Summary
|
|
11
|
-
</div>
|
|
5
|
+
<div class="card-header bg-success text-white">Job Memory Summary</div>
|
|
12
6
|
|
|
13
7
|
<div class="card-body p-0">
|
|
14
|
-
<table class="table table-
|
|
8
|
+
<table class="table table-striped table-hover mb-0">
|
|
15
9
|
<thead class="table-light">
|
|
16
10
|
<tr>
|
|
17
11
|
<th>Job</th>
|
|
18
|
-
<th>
|
|
12
|
+
<th>Avg RSS (ms)</th>
|
|
13
|
+
<th>Avg CPU (ms)</th>
|
|
19
14
|
<th>Runs</th>
|
|
20
15
|
</tr>
|
|
21
16
|
</thead>
|
|
@@ -24,7 +19,8 @@
|
|
|
24
19
|
<% @jobs.each do |job| %>
|
|
25
20
|
<tr>
|
|
26
21
|
<td><strong><%= job[:key] %></strong></td>
|
|
27
|
-
<td><%= job[:avg_mem_kb].round(2)
|
|
22
|
+
<td><%= job[:avg_mem_kb].round(2) %> KB</td>
|
|
23
|
+
<td><%= job[:avg_cpu_ms].round(2) %> ms</td>
|
|
28
24
|
<td><%= job[:count] %></td>
|
|
29
25
|
</tr>
|
|
30
26
|
<% end %>
|
|
@@ -33,10 +29,8 @@
|
|
|
33
29
|
</div>
|
|
34
30
|
</div>
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
data: @rss_chart } %>
|
|
41
|
-
|
|
32
|
+
<%= render "chart",
|
|
33
|
+
title: "RSS Memory (KB)",
|
|
34
|
+
dom_id: "rss_chart",
|
|
35
|
+
data: @rss_chart %>
|
|
42
36
|
</div>
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
<div class="container py-4">
|
|
2
|
-
<h2 class="mb-4 text-info fw-bold">Wall Time</h2>
|
|
2
|
+
<h2 class="mb-4 text-info fw-bold">Wall Time Analysis</h2>
|
|
3
3
|
|
|
4
|
-
<div class="card mb-
|
|
4
|
+
<div class="card mb-4 shadow-sm">
|
|
5
5
|
<div class="card-header bg-info text-white">
|
|
6
|
-
|
|
6
|
+
Wall Time Summary (Last 200 Samples)
|
|
7
7
|
</div>
|
|
8
8
|
|
|
9
9
|
<div class="card-body p-0">
|
|
10
|
-
<table class="table table-
|
|
10
|
+
<table class="table table-striped table-hover mb-0">
|
|
11
11
|
<thead class="table-light">
|
|
12
12
|
<tr>
|
|
13
13
|
<th>Job</th>
|
|
14
|
+
<th>Avg RSS (ms)</th>
|
|
15
|
+
<th>Avg CPU (ms)</th>
|
|
14
16
|
<th>Runs</th>
|
|
15
17
|
</tr>
|
|
16
18
|
</thead>
|
|
19
|
+
|
|
17
20
|
<tbody>
|
|
18
21
|
<% @jobs.each do |job| %>
|
|
19
22
|
<tr>
|
|
20
23
|
<td><strong><%= job[:key] %></strong></td>
|
|
24
|
+
<td><%= job[:avg_mem_kb].round(2) %> KB</td>
|
|
25
|
+
<td><%= job[:avg_cpu_ms].round(2) %> ms</td>
|
|
21
26
|
<td><%= job[:count] %></td>
|
|
22
27
|
</tr>
|
|
23
28
|
<% end %>
|
|
@@ -26,6 +31,8 @@
|
|
|
26
31
|
</div>
|
|
27
32
|
</div>
|
|
28
33
|
|
|
29
|
-
<%= render
|
|
30
|
-
|
|
34
|
+
<%= render "chart",
|
|
35
|
+
title: "Wall Time Trend (ms)",
|
|
36
|
+
dom_id: "wall_chart",
|
|
37
|
+
data: @wall_chart %>
|
|
31
38
|
</div>
|
|
@@ -7,19 +7,22 @@ module SidekiqInsight
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def call(env)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
# ---- BEFORE REQUEST ----
|
|
11
|
+
pm_before = GetProcessMem.new
|
|
12
|
+
rss_before = pm_before.mb * 1024.0
|
|
13
|
+
cpu_before = Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID)
|
|
14
|
+
t_before = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
14
15
|
|
|
15
16
|
status, headers, body = @app.call(env)
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
# ---- AFTER REQUEST ----
|
|
19
|
+
t_after = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
18
20
|
cpu_after = Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID)
|
|
19
|
-
pm_after
|
|
21
|
+
pm_after = GetProcessMem.new
|
|
20
22
|
rss_after = pm_after.mb * 1024.0
|
|
21
23
|
|
|
22
24
|
req = Rack::Request.new(env)
|
|
25
|
+
|
|
23
26
|
sample = {
|
|
24
27
|
path: req.path,
|
|
25
28
|
method: req.request_method,
|
|
@@ -30,6 +33,7 @@ module SidekiqInsight
|
|
|
30
33
|
rss_kb: (rss_after - rss_before)
|
|
31
34
|
}
|
|
32
35
|
|
|
36
|
+
# 🚨 FIX — separate HTTP bucket
|
|
33
37
|
SidekiqInsight.storage.push_sample("__http__#{req.path}", sample)
|
|
34
38
|
|
|
35
39
|
[status, headers, body]
|