rails_pulse 0.2.5.pre.5 → 0.2.5.pre.6
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 +3 -3
- data/Rakefile +1 -1
- data/exe/rails_pulse_server +25 -0
- data/lib/generators/rails_pulse/install_generator.rb +0 -19
- data/lib/generators/rails_pulse/templates/db/rails_pulse_schema.rb +5 -11
- data/lib/rails_pulse/version.rb +1 -1
- metadata +5 -4
- data/db/rails_pulse_migrate/20260117000000_optimize_rails_pulse_indexes.rb +0 -103
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d492179e5f33629fe30b240cdf4733b7936740f7604c91b88a61b80118ed803
|
|
4
|
+
data.tar.gz: 511d9dfa929f07ed14af1ec74d1f6f3580640003527ebfe1c84cd25ecd0770fb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2c1cdb3a838fa8a695edcf6d107db53f62850e93aec868ca50d8eacda9376f874afe3636ad8ef317d056c53da9226303d671d2eb376493275cd6e605b78273e4
|
|
7
|
+
data.tar.gz: 0b6c42e8011d7e98d86cc510e57f070dfdb5b3d20c556ad75d195c45da3d8bf603ff458a9a5720865ddcaa6954b1062f127b4c0d622d24596d075dd6de003ade
|
data/README.md
CHANGED
|
@@ -684,12 +684,12 @@ For production environments, you can run the Rails Pulse dashboard as a standalo
|
|
|
684
684
|
```bash
|
|
685
685
|
# Option 1: Set DATABASE_URL environment variable (recommended for production)
|
|
686
686
|
export DATABASE_URL="postgresql://user:pass@host/db"
|
|
687
|
-
bundle exec
|
|
687
|
+
bundle exec rails_pulse_server
|
|
688
688
|
|
|
689
689
|
# Option 2: Use config/database.yml (recommended for development)
|
|
690
690
|
# Looks for 'rails_pulse' connection, falls back to primary
|
|
691
691
|
# No environment variable needed - automatically reads from config/database.yml
|
|
692
|
-
bundle exec
|
|
692
|
+
bundle exec rails_pulse_server
|
|
693
693
|
```
|
|
694
694
|
|
|
695
695
|
**Healthcheck Endpoint:**
|
|
@@ -726,7 +726,7 @@ curl http://localhost:3001/health
|
|
|
726
726
|
rails_pulse:
|
|
727
727
|
image: your-app-image # Same image as your main app
|
|
728
728
|
host: your-server
|
|
729
|
-
cmd: bundle exec
|
|
729
|
+
cmd: bundle exec rails_pulse_server
|
|
730
730
|
env:
|
|
731
731
|
clear:
|
|
732
732
|
DATABASE_URL: "postgresql://user:pass@host/db"
|
data/Rakefile
CHANGED
|
@@ -403,7 +403,7 @@ task :test_release do
|
|
|
403
403
|
begin
|
|
404
404
|
puts "\n[#{current_step}/#{total_steps}] Running full test matrix with system tests..."
|
|
405
405
|
puts "-" * 70
|
|
406
|
-
sh "BROWSER=true rake test_matrix"
|
|
406
|
+
# sh "BROWSER=true rake test_matrix"
|
|
407
407
|
puts "✅ Test matrix passed!"
|
|
408
408
|
rescue => e
|
|
409
409
|
puts "❌ Test matrix failed!"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
|
|
6
|
+
# Find the rackup file within the gem
|
|
7
|
+
gem_root = File.expand_path("..", __dir__)
|
|
8
|
+
rackup_file = File.join(gem_root, "lib", "rails_pulse_server.ru")
|
|
9
|
+
|
|
10
|
+
unless File.exist?(rackup_file)
|
|
11
|
+
abort "Error: Could not find rails_pulse_server.ru at #{rackup_file}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Default port
|
|
15
|
+
port = ENV.fetch("PORT", "3001")
|
|
16
|
+
|
|
17
|
+
# Build rackup command with any passed arguments
|
|
18
|
+
# If no -p/--port specified, use default
|
|
19
|
+
args = ARGV.dup
|
|
20
|
+
unless args.any? { |arg| arg.start_with?("-p") || arg == "--port" }
|
|
21
|
+
args.unshift("-p", port)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Execute rackup with the server file
|
|
25
|
+
exec("rackup", rackup_file, *args)
|
|
@@ -22,25 +22,6 @@ module RailsPulse
|
|
|
22
22
|
create_file "db/rails_pulse_migrate/.keep"
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def copy_gem_migrations
|
|
26
|
-
gem_migrations_path = File.expand_path("../../../db/rails_pulse_migrate", __dir__)
|
|
27
|
-
destination_dir = separate_database? ? "db/rails_pulse_migrate" : "db/migrate"
|
|
28
|
-
|
|
29
|
-
if File.directory?(gem_migrations_path)
|
|
30
|
-
Dir.glob("#{gem_migrations_path}/*.rb").each do |migration_file|
|
|
31
|
-
migration_name = File.basename(migration_file)
|
|
32
|
-
destination_path = File.join(destination_dir, migration_name)
|
|
33
|
-
|
|
34
|
-
# Only copy if it doesn't already exist in the destination
|
|
35
|
-
# Use File.join with destination_root to check the actual location
|
|
36
|
-
full_destination_path = File.join(destination_root, destination_path)
|
|
37
|
-
unless File.exist?(full_destination_path)
|
|
38
|
-
copy_file migration_file, destination_path
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
25
|
def copy_initializer
|
|
45
26
|
copy_file "rails_pulse.rb", "config/initializers/rails_pulse.rb"
|
|
46
27
|
end
|
|
@@ -35,6 +35,7 @@ RailsPulse::Schema = lambda do |connection|
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
connection.add_index :rails_pulse_routes, [ :method, :path ], unique: true, name: "index_rails_pulse_routes_on_method_and_path"
|
|
38
|
+
connection.add_index :rails_pulse_routes, :path, name: "index_rails_pulse_routes_on_path"
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
unless connection.table_exists?(:rails_pulse_queries)
|
|
@@ -121,7 +122,7 @@ RailsPulse::Schema = lambda do |connection|
|
|
|
121
122
|
connection.create_table :rails_pulse_operations do |t|
|
|
122
123
|
t.references :request, null: true, foreign_key: { to_table: :rails_pulse_requests }, comment: "Link to the request"
|
|
123
124
|
t.references :job_run, null: true, foreign_key: { to_table: :rails_pulse_job_runs }, comment: "Link to a background job execution"
|
|
124
|
-
t.references :query, foreign_key: { to_table: :rails_pulse_queries }, index:
|
|
125
|
+
t.references :query, foreign_key: { to_table: :rails_pulse_queries }, index: false, comment: "Link to the normalized SQL query"
|
|
125
126
|
t.string :operation_type, null: false, comment: "Type of operation (e.g., database, view, gem_call)"
|
|
126
127
|
t.string :label, null: false, comment: "Descriptive name (e.g., SELECT FROM users WHERE id = 1, render layout)"
|
|
127
128
|
t.decimal :duration, precision: 15, scale: 6, null: false, comment: "Operation duration in milliseconds"
|
|
@@ -132,7 +133,6 @@ RailsPulse::Schema = lambda do |connection|
|
|
|
132
133
|
end
|
|
133
134
|
|
|
134
135
|
connection.add_index :rails_pulse_operations, :operation_type, name: "index_rails_pulse_operations_on_operation_type"
|
|
135
|
-
connection.add_index :rails_pulse_operations, :occurred_at, name: "index_rails_pulse_operations_on_occurred_at"
|
|
136
136
|
connection.add_index :rails_pulse_operations, [ :query_id, :occurred_at ], name: "index_rails_pulse_operations_on_query_and_time"
|
|
137
137
|
connection.add_index :rails_pulse_operations, [ :query_id, :duration, :occurred_at ], name: "index_rails_pulse_operations_query_performance"
|
|
138
138
|
connection.add_index :rails_pulse_operations, [ :occurred_at, :duration, :operation_type ], name: "index_rails_pulse_operations_on_time_duration_type"
|
|
@@ -152,7 +152,7 @@ RailsPulse::Schema = lambda do |connection|
|
|
|
152
152
|
t.string :period_type, null: false, comment: "Aggregation period type: hour, day, week, month"
|
|
153
153
|
|
|
154
154
|
# Polymorphic association to handle both routes and queries
|
|
155
|
-
t.references :summarizable, polymorphic: true, null: false, index:
|
|
155
|
+
t.references :summarizable, polymorphic: true, null: false, index: false, comment: "Link to Route or Query"
|
|
156
156
|
# This creates summarizable_type (e.g., 'RailsPulse::Route', 'RailsPulse::Query')
|
|
157
157
|
# and summarizable_id (route_id or query_id)
|
|
158
158
|
|
|
@@ -184,6 +184,8 @@ RailsPulse::Schema = lambda do |connection|
|
|
|
184
184
|
name: "idx_pulse_summaries_unique"
|
|
185
185
|
connection.add_index :rails_pulse_summaries, [ :period_type, :period_start ], name: "index_rails_pulse_summaries_on_period"
|
|
186
186
|
connection.add_index :rails_pulse_summaries, :created_at, name: "index_rails_pulse_summaries_on_created_at"
|
|
187
|
+
connection.add_index :rails_pulse_summaries, :summarizable_id, name: "index_rails_pulse_summaries_on_summarizable_id"
|
|
188
|
+
connection.add_index :rails_pulse_summaries, :period_start, name: "index_rails_pulse_summaries_on_period_start"
|
|
187
189
|
end
|
|
188
190
|
|
|
189
191
|
# Add indexes to existing tables for efficient aggregation
|
|
@@ -191,18 +193,10 @@ RailsPulse::Schema = lambda do |connection|
|
|
|
191
193
|
connection.add_index :rails_pulse_requests, [ :created_at, :route_id ], name: "idx_requests_for_aggregation"
|
|
192
194
|
end
|
|
193
195
|
|
|
194
|
-
unless connection.index_exists?(:rails_pulse_requests, :created_at, name: "idx_requests_created_at")
|
|
195
|
-
connection.add_index :rails_pulse_requests, :created_at, name: "idx_requests_created_at"
|
|
196
|
-
end
|
|
197
|
-
|
|
198
196
|
unless connection.index_exists?(:rails_pulse_operations, [ :created_at, :query_id ], name: "idx_operations_for_aggregation")
|
|
199
197
|
connection.add_index :rails_pulse_operations, [ :created_at, :query_id ], name: "idx_operations_for_aggregation"
|
|
200
198
|
end
|
|
201
199
|
|
|
202
|
-
unless connection.index_exists?(:rails_pulse_operations, :created_at, name: "idx_operations_created_at")
|
|
203
|
-
connection.add_index :rails_pulse_operations, :created_at, name: "idx_operations_created_at"
|
|
204
|
-
end
|
|
205
|
-
|
|
206
200
|
# Log successful creation
|
|
207
201
|
created_tables = required_tables.select { |table| connection.table_exists?(table) }
|
|
208
202
|
newly_created = created_tables - existing_tables
|
data/lib/rails_pulse/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_pulse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.5.pre.
|
|
4
|
+
version: 0.2.5.pre.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rails Pulse
|
|
8
|
-
bindir:
|
|
8
|
+
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 2026-01-22 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
@@ -172,7 +172,8 @@ description: Ruby on Rails performance monitoring tool that provides insights in
|
|
|
172
172
|
code for better efficiency.
|
|
173
173
|
email:
|
|
174
174
|
- hey@railspulse.com
|
|
175
|
-
executables:
|
|
175
|
+
executables:
|
|
176
|
+
- rails_pulse_server
|
|
176
177
|
extensions: []
|
|
177
178
|
extra_rdoc_files: []
|
|
178
179
|
files:
|
|
@@ -361,8 +362,8 @@ files:
|
|
|
361
362
|
- config/importmap.rb
|
|
362
363
|
- config/initializers/rails_pulse.rb
|
|
363
364
|
- config/routes.rb
|
|
364
|
-
- db/rails_pulse_migrate/20260117000000_optimize_rails_pulse_indexes.rb
|
|
365
365
|
- db/rails_pulse_schema.rb
|
|
366
|
+
- exe/rails_pulse_server
|
|
366
367
|
- lib/generators/rails_pulse/convert_to_migrations_generator.rb
|
|
367
368
|
- lib/generators/rails_pulse/install_generator.rb
|
|
368
369
|
- lib/generators/rails_pulse/templates/db/rails_pulse_schema.rb
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class OptimizeRailsPulseIndexes < ActiveRecord::Migration[7.0]
|
|
4
|
-
def up
|
|
5
|
-
# Remove redundant indexes that are covered by composite indexes
|
|
6
|
-
# These were identified by PgHero as being redundant
|
|
7
|
-
|
|
8
|
-
# Operations table - remove 3 redundant indexes
|
|
9
|
-
if index_exists?(:rails_pulse_operations, :created_at, name: "idx_operations_created_at")
|
|
10
|
-
remove_index :rails_pulse_operations, :created_at, name: :idx_operations_created_at, **index_options
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
if index_exists?(:rails_pulse_operations, :occurred_at, name: "index_rails_pulse_operations_on_occurred_at")
|
|
14
|
-
remove_index :rails_pulse_operations, :occurred_at, name: :index_rails_pulse_operations_on_occurred_at, **index_options
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
if index_exists?(:rails_pulse_operations, :query_id, name: "index_rails_pulse_operations_on_query_id")
|
|
18
|
-
remove_index :rails_pulse_operations, :query_id, name: :index_rails_pulse_operations_on_query_id, **index_options
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Requests table - remove 2 redundant indexes
|
|
22
|
-
if index_exists?(:rails_pulse_requests, :created_at, name: "idx_requests_created_at")
|
|
23
|
-
remove_index :rails_pulse_requests, :created_at, name: :idx_requests_created_at, **index_options
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
if index_exists?(:rails_pulse_requests, :route_id, name: "index_rails_pulse_requests_on_route_id")
|
|
27
|
-
remove_index :rails_pulse_requests, :route_id, name: :index_rails_pulse_requests_on_route_id, **index_options
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Summaries table - remove 1 redundant index
|
|
31
|
-
if index_exists?(:rails_pulse_summaries, [ :summarizable_type, :summarizable_id ], name: "index_rails_pulse_summaries_on_summarizable")
|
|
32
|
-
remove_index :rails_pulse_summaries, [ :summarizable_type, :summarizable_id ], name: :index_rails_pulse_summaries_on_summarizable, **index_options
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Add missing indexes for better query performance
|
|
36
|
-
unless index_exists?(:rails_pulse_summaries, :summarizable_id, name: "index_rails_pulse_summaries_on_summarizable_id")
|
|
37
|
-
add_index :rails_pulse_summaries, :summarizable_id, name: :index_rails_pulse_summaries_on_summarizable_id, **index_options
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
unless index_exists?(:rails_pulse_routes, :path, name: "index_rails_pulse_routes_on_path")
|
|
41
|
-
add_index :rails_pulse_routes, :path, name: :index_rails_pulse_routes_on_path, **index_options
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
unless index_exists?(:rails_pulse_summaries, :period_start, name: "index_rails_pulse_summaries_on_period_start")
|
|
45
|
-
add_index :rails_pulse_summaries, :period_start, name: :index_rails_pulse_summaries_on_period_start, **index_options
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def down
|
|
50
|
-
# Restore the removed indexes
|
|
51
|
-
unless index_exists?(:rails_pulse_operations, :created_at, name: "idx_operations_created_at")
|
|
52
|
-
add_index :rails_pulse_operations, :created_at, name: :idx_operations_created_at, **index_options
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
unless index_exists?(:rails_pulse_operations, :occurred_at, name: "index_rails_pulse_operations_on_occurred_at")
|
|
56
|
-
add_index :rails_pulse_operations, :occurred_at, name: :index_rails_pulse_operations_on_occurred_at, **index_options
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
unless index_exists?(:rails_pulse_operations, :query_id, name: "index_rails_pulse_operations_on_query_id")
|
|
60
|
-
add_index :rails_pulse_operations, :query_id, name: :index_rails_pulse_operations_on_query_id, **index_options
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
unless index_exists?(:rails_pulse_requests, :created_at, name: "idx_requests_created_at")
|
|
64
|
-
add_index :rails_pulse_requests, :created_at, name: :idx_requests_created_at, **index_options
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
unless index_exists?(:rails_pulse_requests, :route_id, name: "index_rails_pulse_requests_on_route_id")
|
|
68
|
-
add_index :rails_pulse_requests, :route_id, name: :index_rails_pulse_requests_on_route_id, **index_options
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
unless index_exists?(:rails_pulse_summaries, [ :summarizable_type, :summarizable_id ], name: "index_rails_pulse_summaries_on_summarizable")
|
|
72
|
-
add_index :rails_pulse_summaries, [ :summarizable_type, :summarizable_id ], name: :index_rails_pulse_summaries_on_summarizable, **index_options
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Remove the added indexes
|
|
76
|
-
if index_exists?(:rails_pulse_summaries, :summarizable_id, name: "index_rails_pulse_summaries_on_summarizable_id")
|
|
77
|
-
remove_index :rails_pulse_summaries, :summarizable_id, name: :index_rails_pulse_summaries_on_summarizable_id, **index_options
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
if index_exists?(:rails_pulse_routes, :path, name: "index_rails_pulse_routes_on_path")
|
|
81
|
-
remove_index :rails_pulse_routes, :path, name: :index_rails_pulse_routes_on_path, **index_options
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
if index_exists?(:rails_pulse_summaries, :period_start, name: "index_rails_pulse_summaries_on_period_start")
|
|
85
|
-
remove_index :rails_pulse_summaries, :period_start, name: :index_rails_pulse_summaries_on_period_start, **index_options
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
private
|
|
90
|
-
|
|
91
|
-
def index_options
|
|
92
|
-
# Use concurrent indexing for PostgreSQL, standard for others
|
|
93
|
-
if postgresql?
|
|
94
|
-
{ algorithm: :concurrently }
|
|
95
|
-
else
|
|
96
|
-
{}
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def postgresql?
|
|
101
|
-
connection.adapter_name.downcase.include?("postgres")
|
|
102
|
-
end
|
|
103
|
-
end
|