rails_pulse 0.1.3 → 0.1.4
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 +56 -16
- data/Rakefile +169 -86
- data/app/controllers/rails_pulse/queries_controller.rb +14 -20
- data/app/controllers/rails_pulse/requests_controller.rb +43 -30
- data/app/helpers/rails_pulse/breadcrumbs_helper.rb +1 -1
- data/app/helpers/rails_pulse/chart_helper.rb +1 -1
- data/app/helpers/rails_pulse/formatting_helper.rb +21 -2
- data/app/javascript/rails_pulse/controllers/index_controller.js +11 -3
- data/app/models/rails_pulse/dashboard/tables/slow_queries.rb +1 -1
- data/app/models/rails_pulse/dashboard/tables/slow_routes.rb +1 -1
- data/app/models/rails_pulse/queries/cards/average_query_times.rb +1 -1
- data/app/models/rails_pulse/queries/cards/execution_rate.rb +56 -17
- data/app/models/rails_pulse/queries/cards/percentile_query_times.rb +1 -1
- data/app/models/rails_pulse/queries/charts/average_query_times.rb +3 -7
- data/app/models/rails_pulse/request.rb +1 -1
- data/app/models/rails_pulse/requests/charts/average_response_times.rb +2 -2
- data/app/models/rails_pulse/requests/tables/index.rb +77 -0
- data/app/models/rails_pulse/routes/cards/average_response_times.rb +1 -1
- data/app/models/rails_pulse/routes/cards/error_rate_per_route.rb +1 -1
- data/app/models/rails_pulse/routes/cards/percentile_response_times.rb +1 -1
- data/app/models/rails_pulse/routes/cards/request_count_totals.rb +16 -5
- data/app/models/rails_pulse/routes/tables/index.rb +4 -2
- data/app/models/rails_pulse/summary.rb +7 -7
- data/app/services/rails_pulse/analysis/query_characteristics_analyzer.rb +11 -3
- data/app/views/rails_pulse/components/_metric_card.html.erb +2 -2
- data/app/views/rails_pulse/components/_operation_details_popover.html.erb +1 -1
- data/app/views/rails_pulse/components/_sparkline_stats.html.erb +1 -1
- data/app/views/rails_pulse/dashboard/index.html.erb +1 -1
- data/app/views/rails_pulse/queries/_analysis_results.html.erb +53 -23
- data/app/views/rails_pulse/queries/_show_table.html.erb +33 -5
- data/app/views/rails_pulse/queries/_table.html.erb +3 -7
- data/app/views/rails_pulse/requests/_table.html.erb +30 -19
- data/app/views/rails_pulse/requests/index.html.erb +8 -0
- data/app/views/rails_pulse/requests/show.html.erb +0 -2
- data/app/views/rails_pulse/routes/_requests_table.html.erb +39 -0
- data/app/views/rails_pulse/routes/_table.html.erb +3 -9
- data/app/views/rails_pulse/routes/show.html.erb +3 -5
- data/config/initializers/rails_charts_csp_patch.rb +32 -40
- data/db/migrate/20250930105043_install_rails_pulse_tables.rb +23 -0
- data/db/rails_pulse_schema.rb +1 -1
- data/lib/generators/rails_pulse/convert_to_migrations_generator.rb +25 -9
- data/lib/generators/rails_pulse/install_generator.rb +9 -5
- data/lib/generators/rails_pulse/templates/db/rails_pulse_schema.rb +72 -2
- data/lib/generators/rails_pulse/templates/migrations/install_rails_pulse_tables.rb +3 -2
- data/lib/generators/rails_pulse/upgrade_generator.rb +2 -1
- data/lib/rails_pulse/engine.rb +21 -0
- data/lib/rails_pulse/version.rb +1 -1
- data/public/rails-pulse-assets/rails-pulse.js +1 -1
- data/public/rails-pulse-assets/rails-pulse.js.map +2 -2
- metadata +5 -4
- data/db/migrate/20241222000001_create_rails_pulse_summaries.rb +0 -54
- data/db/migrate/20250916031656_add_analysis_to_rails_pulse_queries.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d5eb9055acbfc951ef6874c484b10f0c4c9a02f4886148fd917ec1f83cdc386
|
4
|
+
data.tar.gz: fe1db6e87b0788868ab99a4c5ee2c818fb2720b8aaa88a59d86023a8a4bc0f92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17141eaefe36c4ee6e857fe36ae3ee7c9e500cb6b3dc07ba79b2ba20248cb1a01920d5f0441c09279af0ab04efa020ffe144aeef1f4fb00036094378c1e2fc65
|
7
|
+
data.tar.gz: 8bf37d00fc3b161eb84587eef5562cebe493adb6a0729897f00aed9d38a69b1847ba82781473a8d2b3deb4ad1acea764b014460a758bc12ef686028096974355
|
data/README.md
CHANGED
@@ -87,15 +87,22 @@ bundle install
|
|
87
87
|
Generate the installation files:
|
88
88
|
|
89
89
|
```bash
|
90
|
+
# Install with single database setup (default - recommended)
|
90
91
|
rails generate rails_pulse:install
|
91
|
-
```
|
92
92
|
|
93
|
-
|
93
|
+
# Or install with separate database setup
|
94
|
+
rails generate rails_pulse:install --database=separate
|
95
|
+
```
|
94
96
|
|
97
|
+
**For single database setup (default):**
|
95
98
|
```bash
|
96
|
-
rails db:
|
99
|
+
rails db:migrate # Creates Rails Pulse tables in your main database
|
97
100
|
```
|
98
101
|
|
102
|
+
**For separate database setup:**
|
103
|
+
1. Configure `config/database.yml` with your Rails Pulse database settings
|
104
|
+
2. Run: `rails db:prepare` to create and load the schema
|
105
|
+
|
99
106
|
Add the Rails Pulse route to your application:
|
100
107
|
|
101
108
|
```ruby
|
@@ -122,6 +129,10 @@ Rails Pulse automatically starts collecting performance data once installed. Acc
|
|
122
129
|
http://localhost:3000/rails_pulse
|
123
130
|
```
|
124
131
|
|
132
|
+
**Database Setup:**
|
133
|
+
- **Single Database (default)**: Rails Pulse tables are created in your main database - no additional configuration needed
|
134
|
+
- **Separate Database**: See the [Separate Database Support](#separate-database-support) section for setup instructions
|
135
|
+
|
125
136
|
### Basic Configuration
|
126
137
|
|
127
138
|
Customize Rails Pulse in `config/initializers/rails_pulse.rb`:
|
@@ -287,20 +298,36 @@ RailsPulse::CleanupJob.perform_later
|
|
287
298
|
|
288
299
|
## Separate Database Support
|
289
300
|
|
290
|
-
Rails Pulse
|
301
|
+
Rails Pulse offers two database setup options to fit your application's needs:
|
302
|
+
|
303
|
+
### Option 1: Single Database (Default - Recommended)
|
304
|
+
|
305
|
+
Stores Rails Pulse data in your main application database alongside your existing tables. This is the simplest setup and works great for most applications.
|
306
|
+
|
307
|
+
**Advantages:**
|
308
|
+
- Zero additional configuration required
|
309
|
+
- Simpler backup and deployment strategies
|
310
|
+
- Works with any database (SQLite, PostgreSQL, MySQL)
|
311
|
+
|
312
|
+
**Installation:**
|
313
|
+
```bash
|
314
|
+
rails generate rails_pulse:install
|
315
|
+
rails db:migrate
|
316
|
+
```
|
317
|
+
|
318
|
+
### Option 2: Separate Database
|
291
319
|
|
292
|
-
|
320
|
+
Stores Rails Pulse data in a dedicated database, completely isolated from your main application.
|
293
321
|
|
322
|
+
**Use a separate database when you want:**
|
294
323
|
- **Isolating monitoring data** from your main application database
|
295
324
|
- **Using different database engines** optimized for time-series data
|
296
325
|
- **Scaling monitoring independently** from your application
|
297
326
|
- **Simplified backup strategies** with separate retention policies
|
298
327
|
|
299
|
-
**For shared database setup (default)**, no database configuration is needed - simply run `rails db:prepare` after installation.
|
300
|
-
|
301
328
|
### Configuration
|
302
329
|
|
303
|
-
To use a separate database, configure the `connects_to` option in your Rails Pulse initializer:
|
330
|
+
To use a separate database, install with the `--database=separate` flag, then configure the `connects_to` option in your Rails Pulse initializer:
|
304
331
|
|
305
332
|
```ruby
|
306
333
|
RailsPulse.configure do |config|
|
@@ -356,17 +383,30 @@ production:
|
|
356
383
|
pool: 5
|
357
384
|
```
|
358
385
|
|
359
|
-
###
|
386
|
+
### Installation Steps
|
360
387
|
|
361
|
-
|
388
|
+
**For separate database setup:**
|
362
389
|
|
363
|
-
|
364
|
-
|
365
|
-
|
390
|
+
1. **Generate installation files:**
|
391
|
+
```bash
|
392
|
+
rails generate rails_pulse:install --database=separate
|
393
|
+
```
|
394
|
+
|
395
|
+
2. **Configure `config/database.yml`** (see examples above)
|
396
|
+
|
397
|
+
3. **Create and load the schema:**
|
398
|
+
```bash
|
399
|
+
rails db:prepare
|
400
|
+
```
|
401
|
+
This automatically creates the database and loads the Rails Pulse schema.
|
402
|
+
|
403
|
+
**Schema Management:**
|
366
404
|
|
367
|
-
|
368
|
-
-
|
369
|
-
-
|
405
|
+
The schema file `db/rails_pulse_schema.rb` serves as your single source of truth for the database structure. It:
|
406
|
+
- Defines all Rails Pulse tables in one place
|
407
|
+
- Is loaded by the installation migration
|
408
|
+
- Should not be deleted or modified
|
409
|
+
- Future updates will provide migrations in `db/rails_pulse_migrate/`
|
370
410
|
|
371
411
|
## Testing
|
372
412
|
|
data/Rakefile
CHANGED
@@ -1,109 +1,192 @@
|
|
1
1
|
require "bundler/setup"
|
2
|
+
require "bundler/gem_tasks"
|
2
3
|
|
3
4
|
# Load environment variables from .env file
|
4
5
|
require "dotenv/load" if File.exist?(".env")
|
5
6
|
|
6
7
|
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
7
8
|
load "rails/tasks/engine.rake"
|
8
|
-
load "rails/tasks/statistics.rake"
|
9
9
|
|
10
|
-
|
10
|
+
desc "Setup database for testing"
|
11
|
+
task :test_setup do
|
12
|
+
database = ENV['DB'] || 'sqlite3'
|
13
|
+
|
14
|
+
puts "\n" + "=" * 50
|
15
|
+
puts "🛠️ Rails Pulse Test Setup"
|
16
|
+
puts "=" * 50
|
17
|
+
puts "Database: #{database.upcase}"
|
18
|
+
puts "=" * 50
|
19
|
+
puts
|
20
|
+
|
21
|
+
begin
|
22
|
+
# Remove schema.rb to ensure clean migration
|
23
|
+
schema_file = "test/dummy/db/schema.rb"
|
24
|
+
if File.exist?(schema_file)
|
25
|
+
puts "🧹 Removing existing schema.rb file..."
|
26
|
+
File.delete(schema_file)
|
27
|
+
end
|
11
28
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
29
|
+
case database.downcase
|
30
|
+
when 'sqlite3', 'sqlite'
|
31
|
+
puts "📦 Setting up SQLite database..."
|
32
|
+
sh "RAILS_ENV=test bin/rails db:drop db:create db:migrate"
|
33
|
+
|
34
|
+
when 'mysql2', 'mysql'
|
35
|
+
puts "🐬 Setting up MySQL database..."
|
36
|
+
sh "DB=mysql2 RAILS_ENV=test rails db:drop db:create db:migrate"
|
37
|
+
|
38
|
+
when 'postgresql', 'postgres'
|
39
|
+
puts "🐘 Setting up PostgreSQL database..."
|
40
|
+
sh "DB=postgresql RAILS_ENV=test rails db:drop db:create db:migrate"
|
41
|
+
|
42
|
+
else
|
43
|
+
puts "⚠️ Unknown database: #{database}"
|
44
|
+
puts "Supported databases: sqlite3, mysql2, postgresql"
|
45
|
+
exit 1
|
46
|
+
end
|
18
47
|
|
19
|
-
|
20
|
-
|
21
|
-
|
48
|
+
puts "\n✅ Database setup complete!"
|
49
|
+
puts "Ready to run: rake test"
|
50
|
+
|
51
|
+
rescue => e
|
52
|
+
puts "\n❌ Database setup failed!"
|
53
|
+
puts "Error: #{e.message}"
|
54
|
+
puts "\nTroubleshooting:"
|
55
|
+
puts "• Ensure #{database} is installed and running"
|
56
|
+
puts "• Check database credentials in test/dummy/config/database.yml"
|
57
|
+
puts "• Verify RAILS_ENV=test environment is configured"
|
58
|
+
exit 1
|
22
59
|
end
|
60
|
+
end
|
23
61
|
|
24
|
-
|
25
|
-
|
26
|
-
|
62
|
+
desc "Run test suite"
|
63
|
+
task :test do
|
64
|
+
database = ENV['DB'] || 'sqlite3'
|
65
|
+
|
66
|
+
# Get Rails version from Gemfile.lock or fallback
|
67
|
+
rails_version = begin
|
68
|
+
require 'rails'
|
69
|
+
Rails.version
|
70
|
+
rescue LoadError
|
71
|
+
# Try to get from Gemfile.lock
|
72
|
+
gemfile_lock = File.read('Gemfile.lock') rescue nil
|
73
|
+
if gemfile_lock && gemfile_lock.match(/rails \(([^)]+)\)/)
|
74
|
+
$1
|
75
|
+
else
|
76
|
+
'unknown'
|
77
|
+
end
|
27
78
|
end
|
28
79
|
|
29
|
-
|
30
|
-
|
31
|
-
|
80
|
+
puts "\n" + "=" * 50
|
81
|
+
puts "💛 Rails Pulse Test Suite"
|
82
|
+
puts "=" * 50
|
83
|
+
puts "Database: #{database.upcase}"
|
84
|
+
puts "Rails: #{rails_version}"
|
85
|
+
puts "=" * 50
|
86
|
+
puts
|
87
|
+
|
88
|
+
sh "rails test test/controllers test/helpers test/instrumentation test/jobs test/models test/services test/system"
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "Setup database for specific Rails version and database"
|
92
|
+
task :test_setup_for_version, [ :database, :rails_version ] do |t, args|
|
93
|
+
database = args[:database] || ENV['DB'] || 'sqlite3'
|
94
|
+
rails_version = args[:rails_version] || 'rails-8-0'
|
95
|
+
|
96
|
+
puts "\n" + "=" * 50
|
97
|
+
puts "🛠️ Rails Pulse Test Setup"
|
98
|
+
puts "=" * 50
|
99
|
+
puts "Database: #{database.upcase}"
|
100
|
+
puts "Rails: #{rails_version.upcase.gsub('-', ' ')}"
|
101
|
+
puts "=" * 50
|
102
|
+
puts
|
103
|
+
|
104
|
+
begin
|
105
|
+
# Remove schema.rb to ensure clean migration
|
106
|
+
schema_file = "test/dummy/db/schema.rb"
|
107
|
+
if File.exist?(schema_file)
|
108
|
+
puts "🧹 Removing existing schema.rb file..."
|
109
|
+
File.delete(schema_file)
|
110
|
+
end
|
111
|
+
|
112
|
+
if rails_version == "rails-8-0" && database == "sqlite3"
|
113
|
+
# Use current default setup
|
114
|
+
puts "📦 Setting up #{database.upcase} database with Rails 8.0..."
|
115
|
+
sh "RAILS_ENV=test bin/rails db:drop db:create db:migrate"
|
116
|
+
else
|
117
|
+
# Use appraisal with specific database and Rails version
|
118
|
+
puts "📦 Setting up #{database.upcase} database with #{rails_version.upcase.gsub('-', ' ')}..."
|
119
|
+
sh "DB=#{database} bundle exec appraisal #{rails_version} rails db:drop db:create db:migrate RAILS_ENV=test"
|
120
|
+
end
|
121
|
+
|
122
|
+
puts "\n✅ Database setup complete for #{database.upcase} + #{rails_version.upcase.gsub('-', ' ')}!"
|
123
|
+
|
124
|
+
rescue => e
|
125
|
+
puts "\n❌ Database setup failed!"
|
126
|
+
puts "Error: #{e.message}"
|
127
|
+
exit 1
|
32
128
|
end
|
129
|
+
end
|
33
130
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
env_vars.merge!({
|
69
|
-
"MYSQL_USERNAME" => ENV.fetch("MYSQL_USERNAME", "root"),
|
70
|
-
"MYSQL_PASSWORD" => ENV.fetch("MYSQL_PASSWORD", "password"),
|
71
|
-
"MYSQL_HOST" => ENV.fetch("MYSQL_HOST", "localhost"),
|
72
|
-
"MYSQL_PORT" => ENV.fetch("MYSQL_PORT", "3306")
|
73
|
-
})
|
74
|
-
end
|
75
|
-
|
76
|
-
# Build environment string
|
77
|
-
env_string = env_vars.map { |k, v| "#{k}=#{v}" }.join(" ")
|
78
|
-
|
79
|
-
# Run the test command
|
80
|
-
sh "#{env_string} bundle exec rails test:all"
|
81
|
-
|
82
|
-
puts "✅ PASSED: #{database} + #{rails_version}"
|
83
|
-
|
84
|
-
rescue => e
|
85
|
-
puts "❌ FAILED: #{database} + #{rails_version}"
|
86
|
-
puts "Error: #{e.message}"
|
87
|
-
failed_combinations << "#{database} + #{rails_version}"
|
131
|
+
desc "Test all database and Rails version combinations"
|
132
|
+
task :test_matrix do
|
133
|
+
databases = %w[sqlite3 postgresql mysql2]
|
134
|
+
rails_versions = %w[rails-7-2 rails-8-0]
|
135
|
+
|
136
|
+
failed_combinations = []
|
137
|
+
total_combinations = databases.size * rails_versions.size
|
138
|
+
current = 0
|
139
|
+
|
140
|
+
puts "\n" + "=" * 60
|
141
|
+
puts "🚀 Rails Pulse Full Test Matrix"
|
142
|
+
puts "=" * 60
|
143
|
+
puts "Testing #{total_combinations} combinations..."
|
144
|
+
puts "=" * 60
|
145
|
+
|
146
|
+
databases.each do |database|
|
147
|
+
rails_versions.each do |rails_version|
|
148
|
+
current += 1
|
149
|
+
|
150
|
+
puts "\n[#{current}/#{total_combinations}] Testing: #{database.upcase} + #{rails_version.upcase.gsub('-', ' ')}"
|
151
|
+
puts "-" * 50
|
152
|
+
|
153
|
+
begin
|
154
|
+
# First setup the database for this specific combination
|
155
|
+
Rake::Task[:test_setup_for_version].reenable
|
156
|
+
Rake::Task[:test_setup_for_version].invoke(database, rails_version)
|
157
|
+
|
158
|
+
# Then run the tests
|
159
|
+
if rails_version == "rails-8-0" && database == "sqlite3"
|
160
|
+
# Current default setup
|
161
|
+
sh "bundle exec rake test"
|
162
|
+
else
|
163
|
+
# Use appraisal with specific database
|
164
|
+
sh "DB=#{database} bundle exec appraisal #{rails_version} rake test"
|
88
165
|
end
|
89
|
-
end
|
90
|
-
end
|
91
166
|
|
92
|
-
|
93
|
-
puts "🏁 Local Test Matrix Results"
|
94
|
-
puts "(CI automatically tests SQLite3 + PostgreSQL only)"
|
95
|
-
puts "=" * 80
|
167
|
+
puts "✅ PASSED: #{database} + #{rails_version}"
|
96
168
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
exit 1
|
169
|
+
rescue => e
|
170
|
+
puts "❌ FAILED: #{database} + #{rails_version}"
|
171
|
+
puts " Error: #{e.message}"
|
172
|
+
failed_combinations << "#{database} + #{rails_version}"
|
173
|
+
end
|
103
174
|
end
|
104
175
|
end
|
176
|
+
|
177
|
+
puts "\n" + "=" * 60
|
178
|
+
puts "🏁 Test Matrix Results"
|
179
|
+
puts "=" * 60
|
180
|
+
|
181
|
+
if failed_combinations.empty?
|
182
|
+
puts "🎉 All #{total_combinations} combinations passed!"
|
183
|
+
else
|
184
|
+
puts "✅ Passed: #{total_combinations - failed_combinations.size}/#{total_combinations}"
|
185
|
+
puts "❌ Failed combinations:"
|
186
|
+
failed_combinations.each { |combo| puts " • #{combo}" }
|
187
|
+
exit 1
|
188
|
+
end
|
105
189
|
end
|
106
190
|
|
107
|
-
|
108
|
-
|
109
|
-
task test: "test:all"
|
191
|
+
|
192
|
+
task default: :test
|
@@ -55,7 +55,7 @@ module RailsPulse
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def table_model
|
58
|
-
|
58
|
+
Summary
|
59
59
|
end
|
60
60
|
|
61
61
|
def chart_class
|
@@ -76,7 +76,10 @@ module RailsPulse
|
|
76
76
|
base_params[:avg_duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
77
77
|
|
78
78
|
if show_action?
|
79
|
-
base_params.merge(
|
79
|
+
base_params.merge(
|
80
|
+
summarizable_id_eq: @query.id,
|
81
|
+
summarizable_type_eq: "RailsPulse::Query"
|
82
|
+
)
|
80
83
|
else
|
81
84
|
base_params
|
82
85
|
end
|
@@ -84,13 +87,14 @@ module RailsPulse
|
|
84
87
|
|
85
88
|
def build_table_ransack_params(ransack_params)
|
86
89
|
if show_action?
|
87
|
-
# For
|
90
|
+
# For Summary model on show page
|
88
91
|
params = ransack_params.merge(
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
+
period_start_gteq: Time.at(@table_start_time),
|
93
|
+
period_start_lt: Time.at(@table_end_time),
|
94
|
+
summarizable_id_eq: @query.id,
|
95
|
+
summarizable_type_eq: "RailsPulse::Query"
|
92
96
|
)
|
93
|
-
params[:
|
97
|
+
params[:avg_duration_gteq] = @start_duration if @start_duration && @start_duration > 0
|
94
98
|
params
|
95
99
|
else
|
96
100
|
# For Summary model on index page
|
@@ -104,23 +108,13 @@ module RailsPulse
|
|
104
108
|
end
|
105
109
|
|
106
110
|
def default_table_sort
|
107
|
-
|
111
|
+
"period_start desc"
|
108
112
|
end
|
109
113
|
|
110
114
|
def build_table_results
|
111
115
|
if show_action?
|
112
|
-
#
|
113
|
-
|
114
|
-
@ransack_query.result
|
115
|
-
.joins(<<~SQL)
|
116
|
-
INNER JOIN rails_pulse_summaries ON
|
117
|
-
rails_pulse_summaries.summarizable_id = rails_pulse_operations.query_id AND
|
118
|
-
rails_pulse_summaries.summarizable_type = 'RailsPulse::Query' AND
|
119
|
-
rails_pulse_summaries.period_type = '#{period_type}' AND
|
120
|
-
rails_pulse_operations.occurred_at >= rails_pulse_summaries.period_start AND
|
121
|
-
rails_pulse_operations.occurred_at < rails_pulse_summaries.period_end
|
122
|
-
SQL
|
123
|
-
.distinct
|
116
|
+
# For Summary model on show page - ransack params already include query ID and type filters
|
117
|
+
@ransack_query.result.where(period_type: period_type)
|
124
118
|
else
|
125
119
|
Queries::Tables::Index.new(
|
126
120
|
ransack_query: @ransack_query,
|
@@ -5,13 +5,7 @@ module RailsPulse
|
|
5
5
|
before_action :set_request, only: :show
|
6
6
|
|
7
7
|
def index
|
8
|
-
|
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
|
+
setup_metric_cards
|
15
9
|
setup_chart_and_table_data
|
16
10
|
end
|
17
11
|
|
@@ -21,12 +15,22 @@ module RailsPulse
|
|
21
15
|
|
22
16
|
private
|
23
17
|
|
18
|
+
def setup_metric_cards
|
19
|
+
return if turbo_frame_request?
|
20
|
+
|
21
|
+
@average_response_times_metric_card = RailsPulse::Routes::Cards::AverageResponseTimes.new(route: nil).to_metric_card
|
22
|
+
@percentile_response_times_metric_card = RailsPulse::Routes::Cards::PercentileResponseTimes.new(route: nil).to_metric_card
|
23
|
+
@request_count_totals_metric_card = RailsPulse::Routes::Cards::RequestCountTotals.new(route: nil).to_metric_card
|
24
|
+
@error_rate_per_route_metric_card = RailsPulse::Routes::Cards::ErrorRatePerRoute.new(route: nil).to_metric_card
|
25
|
+
end
|
26
|
+
|
27
|
+
|
24
28
|
def chart_model
|
25
|
-
Summary
|
29
|
+
RailsPulse::Summary
|
26
30
|
end
|
27
31
|
|
28
32
|
def table_model
|
29
|
-
Request
|
33
|
+
RailsPulse::Request
|
30
34
|
end
|
31
35
|
|
32
36
|
def chart_class
|
@@ -64,27 +68,36 @@ module RailsPulse
|
|
64
68
|
end
|
65
69
|
|
66
70
|
def build_table_results
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
.joins(
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
71
|
+
base_query = @ransack_query.result.includes(:route)
|
72
|
+
|
73
|
+
# If sorting by route_path, we need to join the routes table
|
74
|
+
if @ransack_query.sorts.any? { |sort| sort.name == "route_path" }
|
75
|
+
base_query = base_query.joins(:route)
|
76
|
+
end
|
77
|
+
|
78
|
+
base_query
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def setup_table_data(ransack_params)
|
83
|
+
table_ransack_params = build_table_ransack_params(ransack_params)
|
84
|
+
@ransack_query = table_model.ransack(table_ransack_params)
|
85
|
+
|
86
|
+
# Only apply default sort if not using Requests::Tables::Index (which handles its own sorting)
|
87
|
+
# For requests, we always use the Tables::Index on the index action
|
88
|
+
unless action_name == "index"
|
89
|
+
@ransack_query.sorts = default_table_sort if @ransack_query.sorts.empty?
|
90
|
+
end
|
91
|
+
|
92
|
+
table_results = build_table_results
|
93
|
+
handle_pagination
|
94
|
+
|
95
|
+
@pagy, @table_data = pagy(table_results, limit: session_pagination_limit)
|
96
|
+
end
|
97
|
+
|
98
|
+
def handle_pagination
|
99
|
+
method = pagination_method
|
100
|
+
send(method, params[:limit]) if params[:limit].present?
|
88
101
|
end
|
89
102
|
|
90
103
|
def set_request
|
@@ -3,7 +3,8 @@ module RailsPulse
|
|
3
3
|
def human_readable_occurred_at(occurred_at)
|
4
4
|
return "" unless occurred_at.present?
|
5
5
|
time = occurred_at.is_a?(String) ? Time.parse(occurred_at) : occurred_at
|
6
|
-
|
6
|
+
# Convert to local system timezone (same as charts use)
|
7
|
+
time.getlocal.strftime("%b %d, %Y %l:%M %p")
|
7
8
|
end
|
8
9
|
|
9
10
|
def time_ago_in_words(time)
|
@@ -11,8 +12,10 @@ module RailsPulse
|
|
11
12
|
|
12
13
|
# Convert to Time object if it's a string
|
13
14
|
time = Time.parse(time.to_s) if time.is_a?(String)
|
15
|
+
# Convert to local system timezone for consistent calculation
|
16
|
+
time = time.getlocal
|
14
17
|
|
15
|
-
seconds_ago = Time.
|
18
|
+
seconds_ago = Time.now - time
|
16
19
|
|
17
20
|
case seconds_ago
|
18
21
|
when 0..59
|
@@ -25,5 +28,21 @@ module RailsPulse
|
|
25
28
|
"#{(seconds_ago / 86400).to_i}d ago"
|
26
29
|
end
|
27
30
|
end
|
31
|
+
|
32
|
+
def human_readable_summary_period(summary)
|
33
|
+
return "" unless summary&.period_start&.present? && summary&.period_end&.present?
|
34
|
+
|
35
|
+
# Convert UTC times to local system timezone to match chart display
|
36
|
+
start_time = summary.period_start.getlocal
|
37
|
+
end_time = summary.period_end.getlocal
|
38
|
+
|
39
|
+
|
40
|
+
case summary.period_type
|
41
|
+
when "hour"
|
42
|
+
start_time.strftime("%b %e %Y, %l:%M %p") + " - " + end_time.strftime("%l:%M %p")
|
43
|
+
when "day"
|
44
|
+
start_time.strftime("%b %e, %Y")
|
45
|
+
end
|
46
|
+
end
|
28
47
|
end
|
29
48
|
end
|