activeinsights 0.2.3 → 0.3.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/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
|