rails_pulse 0.1.1 → 0.1.2
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/README.md +72 -176
- data/Rakefile +77 -2
- data/app/assets/stylesheets/rails_pulse/application.css +0 -12
- data/app/controllers/concerns/chart_table_concern.rb +21 -4
- data/app/controllers/concerns/response_range_concern.rb +6 -3
- data/app/controllers/concerns/time_range_concern.rb +5 -10
- data/app/controllers/concerns/zoom_range_concern.rb +1 -1
- data/app/controllers/rails_pulse/application_controller.rb +8 -4
- data/app/controllers/rails_pulse/dashboard_controller.rb +12 -0
- data/app/controllers/rails_pulse/queries_controller.rb +65 -50
- data/app/controllers/rails_pulse/requests_controller.rb +24 -12
- data/app/controllers/rails_pulse/routes_controller.rb +59 -24
- data/app/helpers/rails_pulse/application_helper.rb +0 -1
- data/app/helpers/rails_pulse/chart_formatters.rb +3 -3
- data/app/helpers/rails_pulse/chart_helper.rb +6 -2
- data/app/helpers/rails_pulse/status_helper.rb +10 -4
- data/app/javascript/rails_pulse/controllers/index_controller.js +117 -33
- data/app/javascript/rails_pulse/controllers/pagination_controller.js +17 -27
- data/app/jobs/rails_pulse/backfill_summaries_job.rb +41 -0
- data/app/jobs/rails_pulse/summary_job.rb +53 -0
- data/app/models/rails_pulse/dashboard/charts/average_response_time.rb +28 -7
- data/app/models/rails_pulse/dashboard/charts/p95_response_time.rb +18 -22
- data/app/models/rails_pulse/dashboard/tables/slow_queries.rb +18 -7
- data/app/models/rails_pulse/dashboard/tables/slow_routes.rb +34 -41
- data/app/models/rails_pulse/operation.rb +1 -1
- data/app/models/rails_pulse/queries/cards/average_query_times.rb +47 -23
- data/app/models/rails_pulse/queries/cards/execution_rate.rb +33 -26
- data/app/models/rails_pulse/queries/cards/percentile_query_times.rb +34 -45
- data/app/models/rails_pulse/queries/charts/average_query_times.rb +23 -97
- data/app/models/rails_pulse/queries/tables/index.rb +74 -0
- data/app/models/rails_pulse/query.rb +1 -0
- data/app/models/rails_pulse/requests/charts/average_response_times.rb +23 -84
- data/app/models/rails_pulse/route.rb +1 -6
- data/app/models/rails_pulse/routes/cards/average_response_times.rb +45 -23
- data/app/models/rails_pulse/routes/cards/error_rate_per_route.rb +38 -45
- data/app/models/rails_pulse/routes/cards/percentile_response_times.rb +34 -47
- data/app/models/rails_pulse/routes/cards/request_count_totals.rb +30 -25
- data/app/models/rails_pulse/routes/charts/average_response_times.rb +23 -100
- data/app/models/rails_pulse/routes/tables/index.rb +57 -40
- data/app/models/rails_pulse/summary.rb +143 -0
- data/app/services/rails_pulse/summary_service.rb +199 -0
- data/app/views/layouts/rails_pulse/application.html.erb +4 -4
- data/app/views/rails_pulse/components/_empty_state.html.erb +11 -0
- data/app/views/rails_pulse/components/_metric_card.html.erb +10 -24
- data/app/views/rails_pulse/dashboard/index.html.erb +54 -36
- data/app/views/rails_pulse/queries/_show_table.html.erb +1 -1
- data/app/views/rails_pulse/queries/_table.html.erb +10 -12
- data/app/views/rails_pulse/queries/index.html.erb +41 -34
- data/app/views/rails_pulse/queries/show.html.erb +38 -31
- data/app/views/rails_pulse/requests/_operations.html.erb +32 -26
- data/app/views/rails_pulse/requests/_table.html.erb +1 -3
- data/app/views/rails_pulse/requests/index.html.erb +42 -34
- data/app/views/rails_pulse/routes/_table.html.erb +13 -13
- data/app/views/rails_pulse/routes/index.html.erb +43 -35
- data/app/views/rails_pulse/routes/show.html.erb +42 -35
- data/config/initializers/rails_pulse.rb +0 -12
- data/db/migrate/20241222000001_create_rails_pulse_summaries.rb +54 -0
- data/db/rails_pulse_schema.rb +121 -0
- data/lib/generators/rails_pulse/install_generator.rb +41 -4
- data/lib/generators/rails_pulse/templates/db/rails_pulse_schema.rb +60 -0
- data/lib/generators/rails_pulse/templates/rails_pulse.rb +0 -12
- data/lib/rails_pulse/configuration.rb +0 -11
- data/lib/rails_pulse/engine.rb +0 -1
- data/lib/rails_pulse/version.rb +1 -1
- data/lib/tasks/rails_pulse.rake +58 -0
- data/public/rails-pulse-assets/rails-pulse.css +1 -1
- data/public/rails-pulse-assets/rails-pulse.css.map +1 -1
- data/public/rails-pulse-assets/rails-pulse.js +1 -1
- data/public/rails-pulse-assets/rails-pulse.js.map +3 -3
- data/public/rails-pulse-assets/search.svg +43 -0
- metadata +27 -11
- data/app/controllers/rails_pulse/caches_controller.rb +0 -115
- data/app/helpers/rails_pulse/cached_component_helper.rb +0 -73
- data/app/models/rails_pulse/component_cache_key.rb +0 -33
- data/app/views/rails_pulse/caches/show.html.erb +0 -9
- data/db/migrate/20250227235904_create_routes.rb +0 -12
- data/db/migrate/20250227235915_create_requests.rb +0 -19
- data/db/migrate/20250228000000_create_queries.rb +0 -14
- data/db/migrate/20250228000056_create_operations.rb +0 -24
- data/lib/rails_pulse/migration.rb +0 -29
@@ -6,8 +6,7 @@ module TimeRangeConcern
|
|
6
6
|
const_set(:TIME_RANGE_OPTIONS, [
|
7
7
|
[ "Last 24 hours", :last_day ],
|
8
8
|
[ "Last Week", :last_week ],
|
9
|
-
[ "Last Month", :last_month ]
|
10
|
-
[ "All Time", :all_time ]
|
9
|
+
[ "Last Month", :last_month ]
|
11
10
|
].freeze)
|
12
11
|
end
|
13
12
|
|
@@ -18,23 +17,19 @@ module TimeRangeConcern
|
|
18
17
|
|
19
18
|
ransack_params = params[:q] || {}
|
20
19
|
|
21
|
-
if ransack_params[:
|
22
|
-
# Custom time range from routes index chart zoom which filters requests through an association
|
23
|
-
start_time = parse_time_param(ransack_params[:requests_occurred_at_gteq])
|
24
|
-
end_time = parse_time_param(ransack_params[:requests_occurred_at_lt])
|
25
|
-
elsif ransack_params[:occurred_at_gteq].present?
|
20
|
+
if ransack_params[:occurred_at_gteq].present?
|
26
21
|
# Custom time range from chart zoom where there is no association
|
27
22
|
start_time = parse_time_param(ransack_params[:occurred_at_gteq])
|
28
23
|
end_time = parse_time_param(ransack_params[:occurred_at_lt])
|
29
|
-
elsif ransack_params[:
|
24
|
+
elsif ransack_params[:period_start_range]
|
30
25
|
# Predefined time range from dropdown
|
31
|
-
selected_time_range = ransack_params[:
|
26
|
+
selected_time_range = ransack_params[:period_start_range]
|
32
27
|
start_time =
|
33
28
|
case selected_time_range.to_sym
|
34
29
|
when :last_day then 1.day.ago
|
35
30
|
when :last_week then 1.week.ago
|
36
31
|
when :last_month then 1.month.ago
|
37
|
-
|
32
|
+
else 1.day.ago # Default fallback
|
38
33
|
end
|
39
34
|
end
|
40
35
|
|
@@ -2,8 +2,9 @@ module RailsPulse
|
|
2
2
|
class ApplicationController < ActionController::Base
|
3
3
|
before_action :authenticate_rails_pulse_user!
|
4
4
|
|
5
|
-
def set_pagination_limit
|
6
|
-
|
5
|
+
def set_pagination_limit(limit = nil)
|
6
|
+
limit = limit || params[:limit]
|
7
|
+
session[:pagination_limit] = limit.to_i if limit.present?
|
7
8
|
render json: { status: "ok" }
|
8
9
|
end
|
9
10
|
|
@@ -54,8 +55,11 @@ module RailsPulse
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def session_pagination_limit
|
57
|
-
#
|
58
|
-
session[:pagination_limit] || 10
|
58
|
+
# Use URL param if present, otherwise session, otherwise default
|
59
|
+
limit = params[:limit].presence || session[:pagination_limit] || 10
|
60
|
+
# Update session if URL param was used
|
61
|
+
session[:pagination_limit] = limit.to_i if params[:limit].present?
|
62
|
+
limit.to_i
|
59
63
|
end
|
60
64
|
|
61
65
|
def store_pagination_limit(limit)
|
@@ -1,6 +1,18 @@
|
|
1
1
|
module RailsPulse
|
2
2
|
class DashboardController < ApplicationController
|
3
3
|
def index
|
4
|
+
@average_query_times_metric_card = RailsPulse::Routes::Cards::AverageResponseTimes.new(route: nil).to_metric_card
|
5
|
+
@percentile_response_times_metric_card = RailsPulse::Routes::Cards::PercentileResponseTimes.new(route: nil).to_metric_card
|
6
|
+
@request_count_totals_metric_card = RailsPulse::Routes::Cards::RequestCountTotals.new(route: nil).to_metric_card
|
7
|
+
@error_rate_per_route_metric_card = RailsPulse::Routes::Cards::ErrorRatePerRoute.new(route: nil).to_metric_card
|
8
|
+
|
9
|
+
# Generate chart data for inline rendering
|
10
|
+
@average_response_time_chart_data = RailsPulse::Dashboard::Charts::AverageResponseTime.new.to_chart_data
|
11
|
+
@p95_response_time_chart_data = RailsPulse::Dashboard::Charts::P95ResponseTime.new.to_chart_data
|
12
|
+
|
13
|
+
# Generate table data for inline rendering
|
14
|
+
@slow_routes_table_data = RailsPulse::Dashboard::Tables::SlowRoutes.new.to_table_data
|
15
|
+
@slow_queries_table_data = RailsPulse::Dashboard::Tables::SlowQueries.new.to_table_data
|
4
16
|
end
|
5
17
|
end
|
6
18
|
end
|
@@ -5,21 +5,23 @@ module RailsPulse
|
|
5
5
|
before_action :set_query, only: :show
|
6
6
|
|
7
7
|
def index
|
8
|
+
setup_metric_cards
|
8
9
|
setup_chart_and_table_data
|
9
10
|
end
|
10
11
|
|
11
12
|
def show
|
13
|
+
setup_metric_cards
|
12
14
|
setup_chart_and_table_data
|
13
15
|
end
|
14
16
|
|
15
17
|
private
|
16
18
|
|
17
19
|
def chart_model
|
18
|
-
|
20
|
+
Summary
|
19
21
|
end
|
20
22
|
|
21
23
|
def table_model
|
22
|
-
show_action? ? Operation :
|
24
|
+
show_action? ? Operation : Summary
|
23
25
|
end
|
24
26
|
|
25
27
|
def chart_class
|
@@ -31,73 +33,67 @@ module RailsPulse
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def build_chart_ransack_params(ransack_params)
|
34
|
-
base_params = ransack_params.except(:s)
|
36
|
+
base_params = ransack_params.except(:s).merge(
|
37
|
+
period_start_gteq: Time.at(@start_time),
|
38
|
+
period_start_lt: Time.at(@end_time)
|
39
|
+
)
|
40
|
+
|
41
|
+
# Only add duration filter if we have a meaningful threshold
|
42
|
+
base_params[:avg_duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
35
43
|
|
36
44
|
if show_action?
|
37
|
-
base_params.merge(
|
38
|
-
query_id_eq: @query.id,
|
39
|
-
occurred_at_gteq: @start_time,
|
40
|
-
occurred_at_lt: @end_time,
|
41
|
-
duration_gteq: @start_duration
|
42
|
-
)
|
45
|
+
base_params.merge(summarizable_id_eq: @query.id)
|
43
46
|
else
|
44
|
-
base_params
|
45
|
-
operations_occurred_at_gteq: @start_time,
|
46
|
-
operations_occurred_at_lt: @end_time,
|
47
|
-
operations_duration_gteq: @start_duration
|
48
|
-
)
|
47
|
+
base_params
|
49
48
|
end
|
50
49
|
end
|
51
50
|
|
52
51
|
def build_table_ransack_params(ransack_params)
|
53
52
|
if show_action?
|
54
|
-
|
55
|
-
|
56
|
-
occurred_at_gteq: @table_start_time,
|
57
|
-
occurred_at_lt: @table_end_time,
|
58
|
-
|
53
|
+
# For Operation model on show page
|
54
|
+
params = ransack_params.merge(
|
55
|
+
occurred_at_gteq: Time.at(@table_start_time),
|
56
|
+
occurred_at_lt: Time.at(@table_end_time),
|
57
|
+
query_id_eq: @query.id
|
59
58
|
)
|
59
|
+
params[:duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
60
|
+
params
|
60
61
|
else
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
# For Summary model on index page
|
63
|
+
params = ransack_params.merge(
|
64
|
+
period_start_gteq: Time.at(@table_start_time),
|
65
|
+
period_start_lt: Time.at(@table_end_time)
|
65
66
|
)
|
67
|
+
params[:avg_duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
68
|
+
params
|
66
69
|
end
|
67
70
|
end
|
68
71
|
|
69
72
|
def default_table_sort
|
70
|
-
"occurred_at desc"
|
73
|
+
show_action? ? "occurred_at desc" : "period_start desc"
|
71
74
|
end
|
72
75
|
|
73
76
|
def build_table_results
|
74
77
|
if show_action?
|
75
|
-
@ransack_query.result
|
78
|
+
@ransack_query.result
|
76
79
|
else
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
.group("rails_pulse_queries.id, rails_pulse_queries.normalized_sql, rails_pulse_queries.created_at, rails_pulse_queries.updated_at")
|
84
|
-
.select(
|
85
|
-
"rails_pulse_queries.*",
|
86
|
-
optimized_aggregations_sql
|
87
|
-
)
|
80
|
+
Queries::Tables::Index.new(
|
81
|
+
ransack_query: @ransack_query,
|
82
|
+
period_type: period_type,
|
83
|
+
start_time: @start_time,
|
84
|
+
params: params
|
85
|
+
).to_table
|
88
86
|
end
|
89
87
|
end
|
90
88
|
|
91
89
|
private
|
92
90
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
"MAX(rails_pulse_operations.occurred_at) AS occurred_at"
|
100
|
-
].join(", ")
|
91
|
+
def setup_metric_cards
|
92
|
+
return if turbo_frame_request?
|
93
|
+
|
94
|
+
@average_query_times_metric_card = RailsPulse::Queries::Cards::AverageQueryTimes.new(query: @query).to_metric_card
|
95
|
+
@percentile_query_times_metric_card = RailsPulse::Queries::Cards::PercentileQueryTimes.new(query: @query).to_metric_card
|
96
|
+
@execution_rate_metric_card = RailsPulse::Queries::Cards::ExecutionRate.new(query: @query).to_metric_card
|
101
97
|
end
|
102
98
|
|
103
99
|
def show_action?
|
@@ -108,14 +104,33 @@ module RailsPulse
|
|
108
104
|
show_action? ? :set_pagination_limit : :store_pagination_limit
|
109
105
|
end
|
110
106
|
|
111
|
-
def
|
112
|
-
|
107
|
+
def setup_table_data(ransack_params)
|
108
|
+
table_ransack_params = build_table_ransack_params(ransack_params)
|
109
|
+
@ransack_query = table_model.ransack(table_ransack_params)
|
110
|
+
|
111
|
+
# Only apply default sort if not using Queries::Tables::Index (which handles its own sorting)
|
112
|
+
if show_action?
|
113
|
+
@ransack_query.sorts = default_table_sort if @ransack_query.sorts.empty?
|
114
|
+
end
|
115
|
+
|
116
|
+
table_results = build_table_results
|
117
|
+
handle_pagination
|
118
|
+
|
119
|
+
@pagy, @table_data = pagy(table_results, limit: session_pagination_limit)
|
120
|
+
end
|
121
|
+
|
122
|
+
def handle_pagination
|
123
|
+
method = pagination_method
|
124
|
+
send(method, params[:limit]) if params[:limit].present?
|
113
125
|
end
|
114
126
|
|
115
|
-
def
|
116
|
-
@
|
117
|
-
@
|
118
|
-
|
127
|
+
def setup_time_and_response_ranges
|
128
|
+
@start_time, @end_time, @selected_time_range, @time_diff_hours = setup_time_range
|
129
|
+
@start_duration, @selected_response_range = setup_duration_range(:query)
|
130
|
+
end
|
131
|
+
|
132
|
+
def set_query
|
133
|
+
@query = Query.find(params[:id])
|
119
134
|
end
|
120
135
|
end
|
121
136
|
end
|
@@ -5,6 +5,13 @@ module RailsPulse
|
|
5
5
|
before_action :set_request, only: :show
|
6
6
|
|
7
7
|
def index
|
8
|
+
unless turbo_frame_request?
|
9
|
+
@average_response_times_metric_card = RailsPulse::Routes::Cards::AverageResponseTimes.new(route: nil).to_metric_card
|
10
|
+
@percentile_response_times_metric_card = RailsPulse::Routes::Cards::PercentileResponseTimes.new(route: nil).to_metric_card
|
11
|
+
@request_count_totals_metric_card = RailsPulse::Routes::Cards::RequestCountTotals.new(route: nil).to_metric_card
|
12
|
+
@error_rate_per_route_metric_card = RailsPulse::Routes::Cards::ErrorRatePerRoute.new(route: nil).to_metric_card
|
13
|
+
end
|
14
|
+
|
8
15
|
setup_chart_and_table_data
|
9
16
|
end
|
10
17
|
|
@@ -15,7 +22,7 @@ module RailsPulse
|
|
15
22
|
private
|
16
23
|
|
17
24
|
def chart_model
|
18
|
-
|
25
|
+
Summary
|
19
26
|
end
|
20
27
|
|
21
28
|
def table_model
|
@@ -27,23 +34,27 @@ module RailsPulse
|
|
27
34
|
end
|
28
35
|
|
29
36
|
def chart_options
|
30
|
-
{
|
37
|
+
{}
|
31
38
|
end
|
32
39
|
|
33
40
|
def build_chart_ransack_params(ransack_params)
|
34
|
-
ransack_params.except(:s).merge(
|
35
|
-
|
36
|
-
|
37
|
-
duration_gteq: @start_duration
|
41
|
+
base_params = ransack_params.except(:s).merge(
|
42
|
+
period_start_gteq: Time.at(@start_time),
|
43
|
+
period_start_lt: Time.at(@end_time)
|
38
44
|
)
|
45
|
+
|
46
|
+
# Only add duration filter if we have a meaningful threshold
|
47
|
+
base_params[:avg_duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
48
|
+
base_params
|
39
49
|
end
|
40
50
|
|
41
51
|
def build_table_ransack_params(ransack_params)
|
42
|
-
ransack_params.merge(
|
43
|
-
occurred_at_gteq: @table_start_time,
|
44
|
-
occurred_at_lt: @table_end_time
|
45
|
-
duration_gteq: @start_duration
|
52
|
+
params = ransack_params.merge(
|
53
|
+
occurred_at_gteq: Time.at(@table_start_time),
|
54
|
+
occurred_at_lt: Time.at(@table_end_time)
|
46
55
|
)
|
56
|
+
params[:duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
57
|
+
params
|
47
58
|
end
|
48
59
|
|
49
60
|
def default_table_sort
|
@@ -52,13 +63,14 @@ module RailsPulse
|
|
52
63
|
|
53
64
|
def build_table_results
|
54
65
|
@ransack_query.result
|
55
|
-
.
|
66
|
+
.joins(:route)
|
56
67
|
.select(
|
57
68
|
"rails_pulse_requests.id",
|
58
69
|
"rails_pulse_requests.occurred_at",
|
59
70
|
"rails_pulse_requests.duration",
|
60
71
|
"rails_pulse_requests.status",
|
61
|
-
"rails_pulse_requests.route_id"
|
72
|
+
"rails_pulse_requests.route_id",
|
73
|
+
"rails_pulse_routes.path"
|
62
74
|
)
|
63
75
|
end
|
64
76
|
|
@@ -5,21 +5,32 @@ module RailsPulse
|
|
5
5
|
before_action :set_route, only: :show
|
6
6
|
|
7
7
|
def index
|
8
|
+
setup_metric_cards
|
8
9
|
setup_chart_and_table_data
|
9
10
|
end
|
10
11
|
|
11
12
|
def show
|
13
|
+
setup_metric_cards
|
12
14
|
setup_chart_and_table_data
|
13
15
|
end
|
14
16
|
|
15
17
|
private
|
16
18
|
|
19
|
+
def setup_metric_cards
|
20
|
+
return if turbo_frame_request?
|
21
|
+
|
22
|
+
@average_query_times_metric_card = RailsPulse::Routes::Cards::AverageResponseTimes.new(route: @route).to_metric_card
|
23
|
+
@percentile_response_times_metric_card = RailsPulse::Routes::Cards::PercentileResponseTimes.new(route: @route).to_metric_card
|
24
|
+
@request_count_totals_metric_card = RailsPulse::Routes::Cards::RequestCountTotals.new(route: @route).to_metric_card
|
25
|
+
@error_rate_per_route_metric_card = RailsPulse::Routes::Cards::ErrorRatePerRoute.new(route: @route).to_metric_card
|
26
|
+
end
|
27
|
+
|
17
28
|
def chart_model
|
18
|
-
|
29
|
+
Summary
|
19
30
|
end
|
20
31
|
|
21
32
|
def table_model
|
22
|
-
show_action? ? Request :
|
33
|
+
show_action? ? Request : Summary
|
23
34
|
end
|
24
35
|
|
25
36
|
def chart_class
|
@@ -31,49 +42,53 @@ module RailsPulse
|
|
31
42
|
end
|
32
43
|
|
33
44
|
def build_chart_ransack_params(ransack_params)
|
34
|
-
base_params = ransack_params.except(:s).merge(
|
45
|
+
base_params = ransack_params.except(:s).merge(
|
46
|
+
period_start_gteq: Time.at(@start_time),
|
47
|
+
period_start_lt: Time.at(@end_time)
|
48
|
+
)
|
49
|
+
|
50
|
+
# Only add duration filter if we have a meaningful threshold
|
51
|
+
base_params[:avg_duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
35
52
|
|
36
53
|
if show_action?
|
37
|
-
base_params.merge(
|
38
|
-
route_id_eq: @route.id,
|
39
|
-
occurred_at_gteq: @start_time,
|
40
|
-
occurred_at_lt: @end_time
|
41
|
-
)
|
54
|
+
base_params.merge(summarizable_id_eq: @route.id)
|
42
55
|
else
|
43
|
-
base_params
|
44
|
-
requests_occurred_at_gteq: @start_time,
|
45
|
-
requests_occurred_at_lt: @end_time
|
46
|
-
)
|
56
|
+
base_params
|
47
57
|
end
|
48
58
|
end
|
49
59
|
|
50
60
|
def build_table_ransack_params(ransack_params)
|
51
|
-
base_params = ransack_params.merge(duration_field => @start_duration)
|
52
|
-
|
53
61
|
if show_action?
|
54
|
-
|
55
|
-
|
56
|
-
occurred_at_gteq: @table_start_time,
|
57
|
-
occurred_at_lt: @table_end_time
|
62
|
+
# For Request model on show page
|
63
|
+
params = ransack_params.merge(
|
64
|
+
occurred_at_gteq: Time.at(@table_start_time),
|
65
|
+
occurred_at_lt: Time.at(@table_end_time),
|
66
|
+
route_id_eq: @route.id
|
58
67
|
)
|
68
|
+
params[:duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
69
|
+
params
|
59
70
|
else
|
60
|
-
|
61
|
-
|
62
|
-
|
71
|
+
# For Summary model on index page
|
72
|
+
params = ransack_params.merge(
|
73
|
+
period_start_gteq: Time.at(@table_start_time),
|
74
|
+
period_start_lt: Time.at(@table_end_time)
|
63
75
|
)
|
76
|
+
params[:avg_duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
77
|
+
params
|
64
78
|
end
|
65
79
|
end
|
66
80
|
|
67
81
|
def default_table_sort
|
68
|
-
show_action? ? "occurred_at desc" : "
|
82
|
+
show_action? ? "occurred_at desc" : "avg_duration desc"
|
69
83
|
end
|
70
84
|
|
71
85
|
def build_table_results
|
72
86
|
if show_action?
|
73
|
-
@ransack_query.result
|
87
|
+
@ransack_query.result
|
74
88
|
else
|
75
89
|
Routes::Tables::Index.new(
|
76
90
|
ransack_query: @ransack_query,
|
91
|
+
period_type: period_type,
|
77
92
|
start_time: @start_time,
|
78
93
|
params: params
|
79
94
|
).to_table
|
@@ -81,13 +96,33 @@ module RailsPulse
|
|
81
96
|
end
|
82
97
|
|
83
98
|
def duration_field
|
84
|
-
|
99
|
+
:avg_duration
|
85
100
|
end
|
86
101
|
|
87
102
|
def show_action?
|
88
103
|
action_name == "show"
|
89
104
|
end
|
90
105
|
|
106
|
+
def setup_table_data(ransack_params)
|
107
|
+
table_ransack_params = build_table_ransack_params(ransack_params)
|
108
|
+
@ransack_query = table_model.ransack(table_ransack_params)
|
109
|
+
|
110
|
+
# Only apply default sort if not using Routes::Tables::Index (which handles its own sorting)
|
111
|
+
if show_action?
|
112
|
+
@ransack_query.sorts = default_table_sort if @ransack_query.sorts.empty?
|
113
|
+
end
|
114
|
+
|
115
|
+
table_results = build_table_results
|
116
|
+
handle_pagination
|
117
|
+
|
118
|
+
@pagy, @table_data = pagy(table_results, limit: session_pagination_limit)
|
119
|
+
end
|
120
|
+
|
121
|
+
def handle_pagination
|
122
|
+
method = pagination_method
|
123
|
+
send(method, params[:limit]) if params[:limit].present?
|
124
|
+
end
|
125
|
+
|
91
126
|
def pagination_method
|
92
127
|
show_action? ? :set_pagination_limit : :store_pagination_limit
|
93
128
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module RailsPulse
|
2
2
|
module ChartFormatters
|
3
|
-
def self.
|
3
|
+
def self.period_as_time_or_date(time_diff_hours)
|
4
4
|
if time_diff_hours <= 25
|
5
5
|
<<~JS
|
6
6
|
function(value) {
|
@@ -25,7 +25,7 @@ module RailsPulse
|
|
25
25
|
const data = params[0];
|
26
26
|
const date = new Date(data.axisValue * 1000);
|
27
27
|
const dateString = date.getHours().toString().padStart(2, '0') + ':00';
|
28
|
-
return `${dateString} <br /> ${data.marker} ${parseInt(data.data
|
28
|
+
return `${dateString} <br /> ${data.marker} ${parseInt(data.data)} ms`;
|
29
29
|
}
|
30
30
|
JS
|
31
31
|
else
|
@@ -34,7 +34,7 @@ module RailsPulse
|
|
34
34
|
const data = params[0];
|
35
35
|
const date = new Date(data.axisValue * 1000);
|
36
36
|
const dateString = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
37
|
-
return `${dateString} <br /> ${data.marker} ${parseInt(data.data
|
37
|
+
return `${dateString} <br /> ${data.marker} ${parseInt(data.data)} ms`;
|
38
38
|
}
|
39
39
|
JS
|
40
40
|
end
|
@@ -117,9 +117,13 @@ module RailsPulse
|
|
117
117
|
# Chart data is a hash like: { 1234567890 => { value: 123.45 } }
|
118
118
|
chart_timestamps = chart_data.keys
|
119
119
|
|
120
|
+
# Convert zoom parameters to integers (timestamps)
|
121
|
+
zoom_start_int = zoom_start.respond_to?(:to_i) ? zoom_start.to_i : zoom_start
|
122
|
+
zoom_end_int = zoom_end.respond_to?(:to_i) ? zoom_end.to_i : zoom_end
|
123
|
+
|
120
124
|
if chart_timestamps.any?
|
121
|
-
closest_start = chart_timestamps.min_by { |ts| (ts -
|
122
|
-
closest_end = chart_timestamps.min_by { |ts| (ts -
|
125
|
+
closest_start = chart_timestamps.min_by { |ts| (ts - zoom_start_int).abs }
|
126
|
+
closest_end = chart_timestamps.min_by { |ts| (ts - zoom_end_int).abs }
|
123
127
|
|
124
128
|
# Find the array indices of these timestamps
|
125
129
|
start_index = chart_timestamps.index(closest_start)
|
@@ -256,13 +256,19 @@ module RailsPulse
|
|
256
256
|
|
257
257
|
def event_color(operation_type)
|
258
258
|
case operation_type
|
259
|
-
when "sql"
|
260
|
-
|
261
|
-
when "
|
262
|
-
|
259
|
+
when "sql"
|
260
|
+
"#d27d6b"
|
261
|
+
when "template", "partial", "layout", "collection"
|
262
|
+
"#6c7ab9"
|
263
|
+
when "controller"
|
264
|
+
"#5ba6b0"
|
265
|
+
else
|
266
|
+
"#a6a6a6"
|
263
267
|
end
|
264
268
|
end
|
265
269
|
|
270
|
+
|
271
|
+
|
266
272
|
def duration_options(type = :route)
|
267
273
|
thresholds = RailsPulse.configuration.public_send("#{type}_thresholds")
|
268
274
|
|