activeinsights 0.2.3 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/active_insights/application_controller.rb +5 -1
- data/app/controllers/active_insights/jobs_controller.rb +13 -0
- data/app/controllers/active_insights/jobs_latencies_controller.rb +22 -0
- data/app/controllers/active_insights/jobs_p_values_controller.rb +33 -0
- data/app/controllers/active_insights/jpm_controller.rb +17 -0
- data/app/controllers/active_insights/requests_controller.rb +1 -1
- data/app/controllers/active_insights/requests_p_values_controller.rb +35 -0
- data/app/controllers/active_insights/rpm_controller.rb +1 -1
- data/app/helpers/active_insights/application_helper.rb +1 -1
- data/app/models/active_insights/job.rb +16 -0
- data/app/models/active_insights/record.rb +75 -0
- data/app/models/active_insights/request.rb +6 -70
- data/app/views/active_insights/jobs/index.html.erb +65 -0
- data/app/views/active_insights/jobs_latencies/index.html.erb +27 -0
- data/app/views/active_insights/{controller_p_values → jobs_p_values}/index.html.erb +9 -3
- data/app/views/active_insights/jpm/index.html.erb +26 -0
- data/app/views/active_insights/requests/index.html.erb +11 -7
- data/app/views/active_insights/{p_values → requests_p_values}/index.html.erb +9 -3
- data/app/views/active_insights/rpm/index.html.erb +1 -1
- data/app/views/layouts/active_insights/application.html.erb +7 -0
- data/config/routes.rb +25 -6
- data/db/migrate/{20240111225806_active_insights_request.rb → 20240111225806_create_active_insights_tables.rb} +19 -1
- data/lib/active_insights/engine.rb +11 -10
- data/lib/active_insights/seeders/jobs.rb +81 -0
- data/lib/active_insights/{seeder.rb → seeders/requests.rb} +3 -1
- data/lib/active_insights/version.rb +1 -1
- metadata +16 -10
- data/app/controllers/active_insights/controller_p_values_controller.rb +0 -24
- data/app/controllers/active_insights/p_values_controller.rb +0 -21
- data/vendor/javascript/chart.js.js +0 -10
- data/vendor/javascript/chartkick.js +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e533b9e56ed98672b949403f1ad4ae1b533832abbea5376a6d225b1f73ae14f4
|
4
|
+
data.tar.gz: 20bfedf00b6b878643db9adce6d6608791dd1f0b1a0402219490d7d19cc5d104
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1701580b1caff352a81e719f03e42b18365602c4904926a9d7da1076b44c417a6c416f7c78eb16b04bba158b157affe0d8a011a154cf97d6207bd023e1f2879
|
7
|
+
data.tar.gz: d4e7bbc7ab88d32c723991869909cf083edf40703f367adac38cc6f06fdd73d139de6bfad2758f086e6b688d07fb9394e07770844429ef650153dbc9289cc49a
|
@@ -25,7 +25,7 @@ module ActiveInsights
|
|
25
25
|
end.beginning_of_day
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def base_request_scope
|
29
29
|
scope = ActiveInsights::Request.where(started_at: @date)
|
30
30
|
if ActiveInsights.ignored_endpoints.present?
|
31
31
|
scope = scope.where.
|
@@ -33,5 +33,9 @@ module ActiveInsights
|
|
33
33
|
end
|
34
34
|
scope
|
35
35
|
end
|
36
|
+
|
37
|
+
def base_jobs_scope
|
38
|
+
ActiveInsights::Job.where(started_at: @date)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInsights
|
4
|
+
class JobsController < ApplicationController
|
5
|
+
def index
|
6
|
+
@jobs = base_jobs_scope.with_durations.select(:job, :queue).
|
7
|
+
group(:job, :queue).sort_by(&:agony).reverse
|
8
|
+
|
9
|
+
@latency =
|
10
|
+
base_jobs_scope.select("AVG(queue_time) as latency").to_a.first.latency
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInsights
|
4
|
+
class JobsLatenciesController < ApplicationController
|
5
|
+
def index
|
6
|
+
@latencies = minutes.map do |minute|
|
7
|
+
[minute.pretty_started_at, minute.latency.round(1)]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def redirection
|
12
|
+
redirect_to jobs_latency_path(params[:date])
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def minutes
|
18
|
+
@minutes ||= base_jobs_scope.minute_by_minute.select_started_at.
|
19
|
+
select("AVG(queue_time) as latency")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInsights
|
4
|
+
class JobsPValuesController < ApplicationController
|
5
|
+
def index
|
6
|
+
@p50 = minutes.map{ |minute| [minute.pretty_started_at, minute.p50] }
|
7
|
+
@p95 = minutes.map{ |minute| [minute.pretty_started_at, minute.p95] }
|
8
|
+
@p99 = minutes.map{ |minute| [minute.pretty_started_at, minute.p99] }
|
9
|
+
end
|
10
|
+
|
11
|
+
def redirection
|
12
|
+
if job.present?
|
13
|
+
redirect_to job_p_values_path(params[:date], job)
|
14
|
+
else
|
15
|
+
redirect_to jobs_p_values_path(params[:date])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def minutes
|
22
|
+
@minutes ||= begin
|
23
|
+
scope = base_jobs_scope.minute_by_minute.with_durations
|
24
|
+
scope = scope.where(job:) if job.present?
|
25
|
+
scope.select_started_at
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def job
|
30
|
+
params[:job].presence
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInsights
|
4
|
+
class JpmController < ApplicationController
|
5
|
+
def index
|
6
|
+
@minutes =
|
7
|
+
base_jobs_scope.minute_by_minute.select("COUNT(id) AS jpm").
|
8
|
+
select_started_at.map do |minute|
|
9
|
+
[minute.started_at.strftime("%-l:%M%P"), minute.jpm]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def redirection
|
14
|
+
redirect_to jpm_path(params[:date])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -4,7 +4,7 @@ module ActiveInsights
|
|
4
4
|
class RequestsController < ApplicationController
|
5
5
|
def index
|
6
6
|
@requests =
|
7
|
-
|
7
|
+
base_request_scope.with_durations.select(:formatted_controller).
|
8
8
|
group(:formatted_controller).sort_by(&:agony).reverse
|
9
9
|
end
|
10
10
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInsights
|
4
|
+
class RequestsPValuesController < ApplicationController
|
5
|
+
def index
|
6
|
+
@p50 = minutes.map{ |minute| [minute.pretty_started_at, minute.p50] }
|
7
|
+
@p95 = minutes.map{ |minute| [minute.pretty_started_at, minute.p95] }
|
8
|
+
@p99 = minutes.map{ |minute| [minute.pretty_started_at, minute.p99] }
|
9
|
+
end
|
10
|
+
|
11
|
+
def redirection
|
12
|
+
if formatted_controller.present?
|
13
|
+
redirect_to controller_p_values_path(params[:date],
|
14
|
+
formatted_controller)
|
15
|
+
else
|
16
|
+
redirect_to requests_p_values_path(params[:date])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def minutes
|
23
|
+
@minutes ||= begin
|
24
|
+
scope = base_request_scope.minute_by_minute.with_durations
|
25
|
+
scope = scope.where(formatted_controller:) if
|
26
|
+
formatted_controller.present?
|
27
|
+
scope.select_started_at
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def formatted_controller
|
32
|
+
params[:formatted_controller].presence
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -4,7 +4,7 @@ module ActiveInsights
|
|
4
4
|
class RpmController < ApplicationController
|
5
5
|
def index
|
6
6
|
@minutes =
|
7
|
-
|
7
|
+
base_request_scope.minute_by_minute.select("COUNT(id) AS rpm").
|
8
8
|
select_started_at.map do |minute|
|
9
9
|
[minute.started_at.strftime("%-l:%M%P"), minute.rpm]
|
10
10
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveInsights
|
4
|
+
class Job < ::ActiveInsights::Record
|
5
|
+
def self.setup(started, finished, unique_id, payload)
|
6
|
+
create!(started_at: started, finished_at: finished, uuid: unique_id,
|
7
|
+
db_runtime: payload[:db_runtime], job: payload[:job].class.to_s,
|
8
|
+
queue: payload[:job].queue_name,
|
9
|
+
scheduled_at: payload[:job].scheduled_at)
|
10
|
+
end
|
11
|
+
|
12
|
+
before_validation do
|
13
|
+
self.queue_time ||= (started_at - scheduled_at) * 1000.0
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -5,5 +5,80 @@ module ActiveInsights
|
|
5
5
|
self.abstract_class = true
|
6
6
|
|
7
7
|
connects_to(**ActiveInsights.connects_to) if ActiveInsights.connects_to
|
8
|
+
|
9
|
+
scope :with_durations, lambda {
|
10
|
+
case connection.adapter_name
|
11
|
+
when "SQLite"
|
12
|
+
select("JSON_GROUP_ARRAY(duration) AS durations")
|
13
|
+
when "Mysql2", "Mysql2Spatial", "Mysql2Rgeo", "Trilogy"
|
14
|
+
select("JSON_ARRAYAGG(duration) AS durations")
|
15
|
+
when "PostgreSQL"
|
16
|
+
select("JSON_AGG(duration) AS durations")
|
17
|
+
end
|
18
|
+
}
|
19
|
+
scope :minute_by_minute, lambda {
|
20
|
+
case connection.adapter_name
|
21
|
+
when "SQLite"
|
22
|
+
group("strftime('%Y-%m-%d %H:%M:00 UTC', " \
|
23
|
+
"'#{table_name}'.'started_at')")
|
24
|
+
when "Mysql2", "Mysql2Spatial", "Mysql2Rgeo", "Trilogy"
|
25
|
+
group("CONVERT_TZ(DATE_FORMAT(`#{table_name}`.`started_at`" \
|
26
|
+
", '%Y-%m-%d %H:%i:00'), 'Etc/UTC', '+00:00')")
|
27
|
+
when "PostgreSQL"
|
28
|
+
group("DATE_TRUNC('minute', \"#{table_name}\"." \
|
29
|
+
"\"started_at\"::timestamptz AT TIME ZONE 'Etc/UTC') " \
|
30
|
+
"AT TIME ZONE 'Etc/UTC'")
|
31
|
+
end
|
32
|
+
}
|
33
|
+
scope :select_started_at, lambda {
|
34
|
+
case connection.adapter_name
|
35
|
+
when "SQLite", "Mysql2", "Mysql2Spatial", "Mysql2Rgeo", "Trilogy"
|
36
|
+
select(:started_at)
|
37
|
+
when "PostgreSQL"
|
38
|
+
select("DATE_TRUNC('minute', \"#{table_name}\"." \
|
39
|
+
"\"started_at\"::timestamptz AT TIME ZONE 'Etc/UTC') " \
|
40
|
+
"AT TIME ZONE 'Etc/UTC' as started_at")
|
41
|
+
end
|
42
|
+
}
|
43
|
+
|
44
|
+
before_validation do
|
45
|
+
self.duration ||= (finished_at - started_at) * 1000.0
|
46
|
+
end
|
47
|
+
|
48
|
+
def agony
|
49
|
+
parsed_durations.sum
|
50
|
+
end
|
51
|
+
|
52
|
+
def parsed_durations
|
53
|
+
return unless respond_to?(:durations)
|
54
|
+
|
55
|
+
@parsed_durations ||=
|
56
|
+
if durations.is_a?(Array) then durations
|
57
|
+
else
|
58
|
+
JSON.parse(durations)
|
59
|
+
end.sort
|
60
|
+
end
|
61
|
+
|
62
|
+
def pretty_started_at
|
63
|
+
started_at.strftime("%-l:%M%P")
|
64
|
+
end
|
65
|
+
|
66
|
+
def p50
|
67
|
+
percentile_value(0.5)
|
68
|
+
end
|
69
|
+
|
70
|
+
def p95
|
71
|
+
percentile_value(0.95)
|
72
|
+
end
|
73
|
+
|
74
|
+
def p99
|
75
|
+
percentile_value(0.99)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def percentile_value(percentile)
|
81
|
+
parsed_durations[(percentile * parsed_durations.size).ceil - 1].round(1)
|
82
|
+
end
|
8
83
|
end
|
9
84
|
end
|
@@ -2,76 +2,12 @@
|
|
2
2
|
|
3
3
|
module ActiveInsights
|
4
4
|
class Request < ::ActiveInsights::Record
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
when "PostgreSQL"
|
12
|
-
select("JSON_AGG(duration) AS durations")
|
13
|
-
end
|
14
|
-
}
|
15
|
-
scope :minute_by_minute, lambda {
|
16
|
-
case connection.adapter_name
|
17
|
-
when "SQLite"
|
18
|
-
group("strftime('%Y-%m-%d %H:%M:00 UTC', " \
|
19
|
-
"'active_insights_requests'.'started_at')")
|
20
|
-
when "Mysql2", "Mysql2Spatial", "Mysql2Rgeo", "Trilogy"
|
21
|
-
group("CONVERT_TZ(DATE_FORMAT(`active_insights_requests`.`started_at`" \
|
22
|
-
", '%Y-%m-%d %H:%i:00'), 'Etc/UTC', '+00:00')")
|
23
|
-
when "PostgreSQL"
|
24
|
-
group("DATE_TRUNC('minute', \"active_insights_requests\"." \
|
25
|
-
"\"started_at\"::timestamptz AT TIME ZONE 'Etc/UTC') " \
|
26
|
-
"AT TIME ZONE 'Etc/UTC'")
|
27
|
-
end
|
28
|
-
}
|
29
|
-
scope :select_started_at, lambda {
|
30
|
-
case connection.adapter_name
|
31
|
-
when "SQLite", "Mysql2", "Mysql2Spatial", "Mysql2Rgeo", "Trilogy"
|
32
|
-
select(:started_at)
|
33
|
-
when "PostgreSQL"
|
34
|
-
select("DATE_TRUNC('minute', \"active_insights_requests\"." \
|
35
|
-
"\"started_at\"::timestamptz AT TIME ZONE 'Etc/UTC') " \
|
36
|
-
"AT TIME ZONE 'Etc/UTC' as started_at")
|
37
|
-
end
|
38
|
-
}
|
39
|
-
|
40
|
-
def agony
|
41
|
-
parsed_durations.sum
|
42
|
-
end
|
43
|
-
|
44
|
-
def parsed_durations
|
45
|
-
return unless respond_to?(:durations)
|
46
|
-
|
47
|
-
@parsed_durations ||=
|
48
|
-
if durations.is_a?(Array) then durations
|
49
|
-
else
|
50
|
-
JSON.parse(durations)
|
51
|
-
end.sort
|
52
|
-
end
|
53
|
-
|
54
|
-
def pretty_started_at
|
55
|
-
started_at.strftime("%-l:%M%P")
|
56
|
-
end
|
57
|
-
|
58
|
-
def p50
|
59
|
-
percentile_value(0.5)
|
5
|
+
def self.setup(started, finished, unique_id, payload)
|
6
|
+
create!(started_at: started, finished_at: finished, uuid: unique_id,
|
7
|
+
http_method: payload[:method], **payload.slice(
|
8
|
+
:controller, :action, :format, :status, :view_runtime,
|
9
|
+
:db_runtime
|
10
|
+
))
|
60
11
|
end
|
61
|
-
|
62
|
-
def p95
|
63
|
-
percentile_value(0.95)
|
64
|
-
end
|
65
|
-
|
66
|
-
def p99
|
67
|
-
percentile_value(0.99)
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def percentile_value(percentile)
|
73
|
-
parsed_durations[(percentile * parsed_durations.size).ceil - 1].round(1)
|
74
|
-
end
|
75
|
-
|
76
12
|
end
|
77
13
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
<header>
|
2
|
+
<h1>Metrics for <%= display_date(@date.first) %></h1>
|
3
|
+
<div class="flex flex-row items-center">
|
4
|
+
<%= link_to "View request metrics", active_insights.requests_path, class: "white mr-15px" %>
|
5
|
+
|
6
|
+
<%= form_with url: active_insights.jobs_path, method: :get do |f| %>
|
7
|
+
<%= f.date_field :date, max: Date.current, onchange: "this.form.submit()", value: @date.first.to_date %>
|
8
|
+
<% f.submit "submit", class: "hidden" %>
|
9
|
+
<% end %>
|
10
|
+
</div>
|
11
|
+
</header>
|
12
|
+
|
13
|
+
<div class="pl-30px pt-30px flex flex-row justify-around font-size-30">
|
14
|
+
<% @jobs.flat_map(&:parsed_durations).tap do |durations| %>
|
15
|
+
<%= link_to jpm_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
16
|
+
<div><%= per_minute(durations.size, (@date.last - @date.first).seconds) %></div>
|
17
|
+
<b>JPM</b>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= link_to jobs_p_values_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
21
|
+
<div><%= p50(durations) %> ms</div>
|
22
|
+
<b>p50</b>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<%= link_to jobs_p_values_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
26
|
+
<div><%= p95(durations) %> ms</div>
|
27
|
+
<b>p95</b>
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
<%= link_to jobs_p_values_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
31
|
+
<div><%= p99(durations) %> ms</div>
|
32
|
+
<b>p99</b>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<%= link_to jobs_latency_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
36
|
+
<div><%= @latency.to_f.round(1) %> ms</div>
|
37
|
+
<b>Latency</b>
|
38
|
+
<% end %>
|
39
|
+
<% end %>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
<table>
|
43
|
+
<thead>
|
44
|
+
<tr>
|
45
|
+
<th>Name</th>
|
46
|
+
<th>Queue</th>
|
47
|
+
<th>JPM</th>
|
48
|
+
<th>p50</th>
|
49
|
+
<th>p95</th>
|
50
|
+
<th>p99</th>
|
51
|
+
</tr>
|
52
|
+
</thead>
|
53
|
+
<tbody>
|
54
|
+
<% @jobs.each do |model| %>
|
55
|
+
<tr>
|
56
|
+
<td><%= link_to model.job, job_p_values_path(@date.first.to_date, model.job) %></td>
|
57
|
+
<td><%= model.queue %></td>
|
58
|
+
<td><%= per_minute(model.parsed_durations.size, (@date.last - @date.first).seconds) %></td>
|
59
|
+
<td><%= model.p50 %> ms</td>
|
60
|
+
<td><%= model.p95 %> ms</td>
|
61
|
+
<td><%= model.p99 %> ms</td>
|
62
|
+
</tr>
|
63
|
+
<% end %>
|
64
|
+
</tbody>
|
65
|
+
</table>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<header>
|
2
|
+
<h1>Job Latency for <%= display_date(@date.first) %> (in ms)</h1>
|
3
|
+
|
4
|
+
<%= form_with url: active_insights.jobs_latency_redirection_path, method: :get do |f| %>
|
5
|
+
<%= f.date_field :date, max: Date.current, onchange: "this.form.submit()", value: @date.first.to_date %>
|
6
|
+
<% f.submit "submit", class: "hidden" %>
|
7
|
+
<% end %>
|
8
|
+
</header>
|
9
|
+
|
10
|
+
<div class="p-16px">
|
11
|
+
<%= column_chart @latencies, height: "80%", colors: ["#C00"], library: {
|
12
|
+
borderSkipped: true, barPercentage: 1, categoryPercentage: 1,
|
13
|
+
plugins: { zoom: { zoom: { wheel: { enabled: false }, drag: { enabled: true, backgroundColor: 'rgba(225,225,225,0.5)' }, mode: 'x' } } },
|
14
|
+
scales: {
|
15
|
+
x: { barPercentage: 1.0, autoSkip: false, display: false },
|
16
|
+
y: { grid: { display: false }, ticks: { color: "white" }, min: (@latencies.map(&:second).min.to_f * 0.98).ceil, max: (@latencies.map(&:second).max) }
|
17
|
+
} } %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<script>
|
21
|
+
document.addEventListener('keydown',(event) => {
|
22
|
+
const chart = Chartkick.charts[Object.keys(Chartkick.charts)[0]].getChartObject()
|
23
|
+
if (event.key === 'Escape' || event.key === 'Esc') {
|
24
|
+
chart.resetZoom()
|
25
|
+
}
|
26
|
+
});
|
27
|
+
</script>
|
@@ -1,6 +1,12 @@
|
|
1
1
|
<header>
|
2
|
-
|
3
|
-
|
2
|
+
<% if params[:job].present? %>
|
3
|
+
<h1><%= params[:job] %> metrics for <%= display_date(@date.first) %> (in ms)</h1>
|
4
|
+
<% else %>
|
5
|
+
<h1>Job Metrics for <%= display_date(@date.first) %> (in ms)</h1>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<%= form_with url: active_insights.jobs_p_values_redirection_path, method: :get do |f| %>
|
9
|
+
<%= f.hidden_field :job, value: params[:job] %>
|
4
10
|
<%= f.date_field :date, max: Date.current, onchange: "this.form.submit()", value: @date.first.to_date %>
|
5
11
|
<% f.submit "submit", class: "hidden" %>
|
6
12
|
<% end %>
|
@@ -12,7 +18,7 @@
|
|
12
18
|
elements: { point: { radius: 0 } },
|
13
19
|
scales: {
|
14
20
|
x: { autoSkip: false, display: false },
|
15
|
-
y: { grid: { display: false }, ticks: { color: "white" }, min: (@p50.map(&:second).min * 0.98).ceil, max: (@p99.map(&:second).max) }
|
21
|
+
y: { grid: { display: false }, ticks: { color: "white" }, min: (@p50.map(&:second).min.to_f * 0.98).ceil, max: (@p99.map(&:second).max) }
|
16
22
|
} } %>
|
17
23
|
</div>
|
18
24
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<header>
|
2
|
+
<h1>JPM Metrics for <%= display_date(@date.first) %></h1>
|
3
|
+
<%= form_with url: active_insights.jpm_redirection_path, method: :get do |f| %>
|
4
|
+
<%= f.date_field :date, max: Date.current, onchange: "this.form.submit()", value: @date.first.to_date %>
|
5
|
+
<% f.submit "submit", class: "hidden" %>
|
6
|
+
<% end %>
|
7
|
+
</header>
|
8
|
+
|
9
|
+
<div class="p-16px">
|
10
|
+
<%= column_chart @minutes, height: "80%", colors: ["#C00"], library: {
|
11
|
+
borderSkipped: true, barPercentage: 1, categoryPercentage: 1,
|
12
|
+
plugins: { zoom: { zoom: { wheel: { enabled: false }, drag: { enabled: true, backgroundColor: 'rgba(225,225,225,0.5)' }, mode: 'x' } } },
|
13
|
+
scales: {
|
14
|
+
x: { barPercentage: 1.0, autoSkip: false, display: false },
|
15
|
+
y: { grid: { display: false }, ticks: { color: "white" }, min: (@minutes.map(&:second).min.to_f * 0.98).ceil, max: (@minutes.map(&:second).max) }
|
16
|
+
} } %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<script>
|
20
|
+
document.addEventListener('keydown',(event) => {
|
21
|
+
const chart = Chartkick.charts[Object.keys(Chartkick.charts)[0]].getChartObject()
|
22
|
+
if (event.key === 'Escape' || event.key === 'Esc') {
|
23
|
+
chart.resetZoom()
|
24
|
+
}
|
25
|
+
});
|
26
|
+
</script>
|
@@ -1,9 +1,13 @@
|
|
1
1
|
<header>
|
2
2
|
<h1>Metrics for <%= display_date(@date.first) %></h1>
|
3
|
-
|
4
|
-
<%=
|
5
|
-
|
6
|
-
|
3
|
+
<div class="flex flex-row items-center">
|
4
|
+
<%= link_to "View job metrics", active_insights.jobs_path, class: "white mr-15px" %>
|
5
|
+
|
6
|
+
<%= form_with url: active_insights.requests_path, method: :get do |f| %>
|
7
|
+
<%= f.date_field :date, max: Date.current, onchange: "this.form.submit()", value: @date.first.to_date %>
|
8
|
+
<% f.submit "submit", class: "hidden" %>
|
9
|
+
<% end %>
|
10
|
+
</div>
|
7
11
|
</header>
|
8
12
|
|
9
13
|
<div class="pl-30px pt-30px flex flex-row justify-around font-size-30">
|
@@ -13,17 +17,17 @@
|
|
13
17
|
<b>RPM</b>
|
14
18
|
<% end %>
|
15
19
|
|
16
|
-
<%= link_to
|
20
|
+
<%= link_to requests_p_values_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
17
21
|
<div><%= p50(durations) %> ms</div>
|
18
22
|
<b>p50</b>
|
19
23
|
<% end %>
|
20
24
|
|
21
|
-
<%= link_to
|
25
|
+
<%= link_to requests_p_values_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
22
26
|
<div><%= p95(durations) %> ms</div>
|
23
27
|
<b>p95</b>
|
24
28
|
<% end %>
|
25
29
|
|
26
|
-
<%= link_to
|
30
|
+
<%= link_to requests_p_values_path(@date.first.to_date), class: "flex flex-col justify-center items-center no-underline" do %>
|
27
31
|
<div><%= p99(durations) %> ms</div>
|
28
32
|
<b>p99</b>
|
29
33
|
<% end %>
|
@@ -1,6 +1,12 @@
|
|
1
1
|
<header>
|
2
|
-
|
3
|
-
|
2
|
+
<% if params[:formatted_controller].present? %>
|
3
|
+
<h1><%= params[:formatted_controller] %> metrics for <%= display_date(@date.first) %> (in ms)</h1>
|
4
|
+
<% else %>
|
5
|
+
<h1>Response Metrics for <%= display_date(@date.first) %> (in ms)</h1>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<%= form_with url: active_insights.requests_p_values_redirection_path, method: :get do |f| %>
|
9
|
+
<%= f.hidden_field :formatted_controller, value: params[:formatted_controller] %>
|
4
10
|
<%= f.date_field :date, max: Date.current, onchange: "this.form.submit()", value: @date.first.to_date %>
|
5
11
|
<% f.submit "submit", class: "hidden" %>
|
6
12
|
<% end %>
|
@@ -12,7 +18,7 @@
|
|
12
18
|
elements: { point: { radius: 0 } },
|
13
19
|
scales: {
|
14
20
|
x: { autoSkip: false, display: false },
|
15
|
-
y: { grid: { display: false }, ticks: { color: "white" }, min: (@p50.map(&:second).min * 0.98).ceil, max: (@p99.map(&:second).max) }
|
21
|
+
y: { grid: { display: false }, ticks: { color: "white" }, min: (@p50.map(&:second).min.to_f * 0.98).ceil, max: (@p99.map(&:second).max) }
|
16
22
|
} } %>
|
17
23
|
</div>
|
18
24
|
|
@@ -12,7 +12,7 @@
|
|
12
12
|
plugins: { zoom: { zoom: { wheel: { enabled: false }, drag: { enabled: true, backgroundColor: 'rgba(225,225,225,0.5)' }, mode: 'x' } } },
|
13
13
|
scales: {
|
14
14
|
x: { barPercentage: 1.0, autoSkip: false, display: false },
|
15
|
-
y: { grid: { display: false }, ticks: { color: "white" }, min: (@minutes.map(&:second).min * 0.98).ceil, max: (@minutes.map(&:second).max) }
|
15
|
+
y: { grid: { display: false }, ticks: { color: "white" }, min: (@minutes.map(&:second).min.to_f * 0.98).ceil, max: (@minutes.map(&:second).max) }
|
16
16
|
} } %>
|
17
17
|
</div>
|
18
18
|
|
data/config/routes.rb
CHANGED
@@ -1,19 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
ActiveInsights::Engine.routes.draw do
|
3
|
+
ActiveInsights::Engine.routes.draw do # rubocop:disable Metrics/BlockLength
|
4
4
|
resources :requests, only: %i(index)
|
5
|
+
resources :jobs, only: %i(index)
|
6
|
+
get "/jobs/:date", to: "jobs#index"
|
5
7
|
get "/requests/:date", to: "requests#index"
|
8
|
+
|
6
9
|
get "/requests/rpm/redirection", to: "rpm#redirection", as: :rpm_redirection
|
7
10
|
get "/requests/:date/rpm", to: "rpm#index", as: :rpm
|
8
11
|
|
9
|
-
get "/requests/p_values/redirection", to: "
|
10
|
-
as: :
|
11
|
-
get "/requests/:date/p_values", to: "
|
12
|
+
get "/requests/p_values/redirection", to: "requests_p_values#redirection",
|
13
|
+
as: :requests_p_values_redirection
|
14
|
+
get "/requests/:date/p_values", to: "requests_p_values#index", as: :requests_p_values
|
12
15
|
get "/requests/:date/:formatted_controller/p_values",
|
13
|
-
to: "
|
16
|
+
to: "requests_p_values#index", as: :controller_p_values
|
14
17
|
get "/requests/:formatted_controller/p_values/redirection",
|
15
|
-
to: "
|
18
|
+
to: "requests_p_values#redirection",
|
16
19
|
as: :controller_p_values_redirection
|
17
20
|
|
21
|
+
get "/jobs/jpm/redirection", to: "jpm#redirection", as: :jpm_redirection
|
22
|
+
get "/jobs/:date/jpm", to: "jpm#index", as: :jpm
|
23
|
+
|
24
|
+
get "/jobs/p_values/redirection", to: "jobs_p_values#redirection",
|
25
|
+
as: :jobs_p_values_redirection
|
26
|
+
get "/jobs/:date/p_values", to: "jobs_p_values#index", as: :jobs_p_values
|
27
|
+
|
28
|
+
get "/jobs/:date/:job/p_values", to: "jobs_p_values#index", as: :job_p_values
|
29
|
+
get "/jobs/:job/p_values/redirection",
|
30
|
+
to: "jobs_p_values#redirection",
|
31
|
+
as: :job_p_values_redirection
|
32
|
+
|
33
|
+
get "/jobs/:date/latencies", to: "jobs_latencies#index", as: :jobs_latency
|
34
|
+
get "/jobs/latencies/redirection", to: "jobs_latencies#redirection",
|
35
|
+
as: :jobs_latency_redirection
|
36
|
+
|
18
37
|
root "requests#index"
|
19
38
|
end
|