rails-health-checker 0.1.0 → 0.2.0

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.
@@ -1,182 +0,0 @@
1
- module RailsHealthChecker
2
- class SystemAnalyzer
3
- def analyze
4
- {
5
- rails_info: rails_system_info,
6
- required_libs: check_required_libraries,
7
- optional_libs: check_optional_libraries,
8
- server_requirements: check_server_requirements,
9
- cable_info: check_action_cable,
10
- environment_info: environment_details
11
- }
12
- end
13
-
14
- private
15
-
16
- def rails_system_info
17
- {
18
- version: Rails.version,
19
- environment: Rails.env,
20
- root: Rails.root.to_s,
21
- config_loaded: Rails.application.config.loaded?,
22
- eager_load: Rails.application.config.eager_load,
23
- cache_classes: Rails.application.config.cache_classes
24
- }
25
- rescue => e
26
- { error: e.message }
27
- end
28
-
29
- def check_required_libraries
30
- required = {
31
- 'bundler' => { required: true, available: defined?(Bundler), purpose: 'Dependency management' },
32
- 'rack' => { required: true, available: defined?(Rack), purpose: 'Web server interface' },
33
- 'activerecord' => { required: true, available: defined?(ActiveRecord), purpose: 'Database ORM' },
34
- 'actionpack' => { required: true, available: defined?(ActionPack), purpose: 'Web framework core' },
35
- 'activesupport' => { required: true, available: defined?(ActiveSupport), purpose: 'Core extensions' }
36
- }
37
-
38
- required.each do |name, info|
39
- info[:status] = info[:available] ? 'loaded' : 'missing'
40
- info[:version] = get_gem_version(name) if info[:available]
41
- end
42
-
43
- required
44
- end
45
-
46
- def check_optional_libraries
47
- optional = {
48
- 'sidekiq' => { available: defined?(Sidekiq), purpose: 'Background job processing' },
49
- 'resque' => { available: defined?(Resque), purpose: 'Background job processing' },
50
- 'redis' => { available: defined?(Redis), purpose: 'In-memory data store' },
51
- 'puma' => { available: defined?(Puma), purpose: 'Web server' },
52
- 'unicorn' => { available: defined?(Unicorn), purpose: 'Web server' },
53
- 'passenger' => { available: defined?(PhusionPassenger), purpose: 'Web server' },
54
- 'devise' => { available: defined?(Devise), purpose: 'Authentication' },
55
- 'cancancan' => { available: defined?(CanCan), purpose: 'Authorization' },
56
- 'turbo-rails' => { available: defined?(Turbo), purpose: 'SPA-like experience' },
57
- 'stimulus-rails' => { available: defined?(Stimulus), purpose: 'JavaScript framework' },
58
- 'bootsnap' => { available: defined?(Bootsnap), purpose: 'Boot optimization' },
59
- 'sprockets' => { available: defined?(Sprockets), purpose: 'Asset pipeline' }
60
- }
61
-
62
- optional.each do |name, info|
63
- info[:status] = info[:available] ? 'loaded' : 'not_loaded'
64
- info[:version] = get_gem_version(name) if info[:available]
65
- end
66
-
67
- optional
68
- end
69
-
70
- def check_server_requirements
71
- {
72
- web_server: detect_web_server,
73
- database: detect_database_adapter,
74
- cache_store: detect_cache_store,
75
- session_store: detect_session_store,
76
- asset_host: (Rails.application.config.asset_host rescue nil)
77
- }
78
- end
79
-
80
- def check_action_cable
81
- return { available: false } unless defined?(ActionCable)
82
-
83
- {
84
- available: true,
85
- adapter: (ActionCable.server.config.cable[:adapter] rescue 'unknown'),
86
- url: (ActionCable.server.config.cable[:url] rescue nil),
87
- allowed_request_origins: (ActionCable.server.config.allowed_request_origins rescue []),
88
- status: action_cable_status
89
- }
90
- end
91
-
92
- def environment_details
93
- {
94
- ruby_version: RUBY_VERSION,
95
- ruby_platform: RUBY_PLATFORM,
96
- rails_env: Rails.env,
97
- rack_env: ENV['RACK_ENV'],
98
- database_url: ENV['DATABASE_URL'] ? 'configured' : 'not_set',
99
- redis_url: ENV['REDIS_URL'] ? 'configured' : 'not_set',
100
- secret_key_base: ENV['SECRET_KEY_BASE'] ? 'configured' : 'not_set'
101
- }
102
- end
103
-
104
- def get_gem_version(gem_name)
105
- Gem.loaded_specs[gem_name]&.version&.to_s || 'unknown'
106
- rescue
107
- 'unknown'
108
- end
109
-
110
- def detect_web_server
111
- return 'puma' if defined?(Puma)
112
- return 'unicorn' if defined?(Unicorn)
113
- return 'passenger' if defined?(PhusionPassenger)
114
- return 'thin' if defined?(Thin)
115
- return 'webrick' if defined?(WEBrick)
116
- 'unknown'
117
- end
118
-
119
- def detect_database_adapter
120
- ActiveRecord::Base.connection.adapter_name
121
- rescue
122
- 'unknown'
123
- end
124
-
125
- def detect_cache_store
126
- cache_class = Rails.cache.class.name
127
- {
128
- type: cache_class,
129
- explanation: get_cache_explanation(cache_class),
130
- recommendation: get_cache_recommendation(cache_class)
131
- }
132
- rescue
133
- {
134
- type: 'unknown',
135
- explanation: 'Unable to detect cache store',
136
- recommendation: 'Check Rails cache configuration'
137
- }
138
- end
139
-
140
- def detect_session_store
141
- Rails.application.config.session_store.name
142
- rescue
143
- 'unknown'
144
- end
145
-
146
- def action_cable_status
147
- return 'healthy' if ActionCable.server.config.cable[:adapter] != 'test'
148
- 'not_configured'
149
- rescue
150
- 'error'
151
- end
152
-
153
- def get_cache_explanation(cache_class)
154
- explanations = {
155
- 'ActiveSupport::Cache::NullStore' => 'No caching (common in development)',
156
- 'ActiveSupport::Cache::MemoryStore' => 'In-memory caching (single process)',
157
- 'ActiveSupport::Cache::FileStore' => 'File-based caching (disk storage)',
158
- 'ActiveSupport::Cache::RedisStore' => 'Redis-based caching (recommended for production)',
159
- 'ActiveSupport::Cache::MemCacheStore' => 'Memcached-based caching (production ready)',
160
- 'ActiveSupport::Cache::RedisCacheStore' => 'Redis caching with Rails 5.2+ features'
161
- }
162
- explanations[cache_class] || 'Custom or unknown cache store'
163
- end
164
-
165
- def get_cache_recommendation(cache_class)
166
- case cache_class
167
- when 'ActiveSupport::Cache::NullStore'
168
- Rails.env.production? ? 'Configure Redis or Memcached for production' : 'OK for development'
169
- when 'ActiveSupport::Cache::MemoryStore'
170
- 'Consider Redis/Memcached for multi-server deployments'
171
- when 'ActiveSupport::Cache::FileStore'
172
- 'Consider Redis/Memcached for better performance'
173
- when 'ActiveSupport::Cache::RedisStore', 'ActiveSupport::Cache::RedisCacheStore'
174
- 'Excellent choice for production'
175
- when 'ActiveSupport::Cache::MemCacheStore'
176
- 'Good choice for production'
177
- else
178
- 'Verify cache store configuration'
179
- end
180
- end
181
- end
182
- end
@@ -1,63 +0,0 @@
1
- namespace :health do
2
- desc "Run comprehensive health check"
3
- task check: :environment do
4
- RailsHealthChecker.check
5
- end
6
-
7
- desc "Check gem dependencies"
8
- task gems: :environment do
9
- analyzer = RailsHealthChecker::GemAnalyzer.new
10
- results = analyzer.analyze
11
-
12
- puts "=== Gem Health Report ==="
13
- puts "Total gems: #{results[:total]}"
14
- puts "Outdated gems: #{results[:outdated]}"
15
- puts "Vulnerable gems: #{results[:vulnerable]}"
16
- puts "========================="
17
- end
18
-
19
- desc "Check database connectivity"
20
- task database: :environment do
21
- begin
22
- ActiveRecord::Base.connection.active?
23
- puts "✓ Database connection: healthy"
24
- rescue => e
25
- puts "✗ Database connection: failed (#{e.message})"
26
- end
27
- end
28
-
29
- desc "Check background jobs health"
30
- task jobs: :environment do
31
- analyzer = RailsHealthChecker::JobAnalyzer.new
32
- results = analyzer.analyze
33
-
34
- puts "=== Background Jobs Health ==="
35
- puts "Overall Status: #{results[:status]}"
36
-
37
- if results[:sidekiq][:available]
38
- sidekiq = results[:sidekiq]
39
- puts "\nSidekiq:"
40
- puts " Status: #{sidekiq[:status]}"
41
- puts " Enqueued: #{sidekiq[:enqueued]}" unless sidekiq[:error]
42
- puts " Failed: #{sidekiq[:failed]}" unless sidekiq[:error]
43
- end
44
-
45
- if results[:resque][:available]
46
- resque = results[:resque]
47
- puts "\nResque:"
48
- puts " Status: #{resque[:status]}"
49
- puts " Pending: #{resque[:pending]}" unless resque[:error]
50
- puts " Failed: #{resque[:failed]}" unless resque[:error]
51
- end
52
-
53
- puts "============================="
54
- end
55
-
56
- desc "Generate detailed health report file"
57
- task report: :environment do
58
- results = RailsHealthChecker::Checker.new.run
59
- report_generator = RailsHealthChecker::ReportGenerator.new(results)
60
- filename = report_generator.save_to_file
61
- puts "📄 Health report updated: #{filename}"
62
- end
63
- end
@@ -1,3 +0,0 @@
1
- module RailsHealthChecker
2
- VERSION = "0.1.0"
3
- end
@@ -1,17 +0,0 @@
1
- require_relative "rails_health_checker/version"
2
- require_relative "rails_health_checker/checker"
3
- require_relative "rails_health_checker/gem_analyzer"
4
- require_relative "rails_health_checker/job_analyzer"
5
- require_relative "rails_health_checker/system_analyzer"
6
- require_relative "rails_health_checker/health_middleware"
7
- require_relative "rails_health_checker/dashboard_middleware"
8
- require_relative "rails_health_checker/report_generator"
9
- require_relative "rails_health_checker/railtie" if defined?(Rails)
10
-
11
- module RailsHealthChecker
12
- class Error < StandardError; end
13
-
14
- def self.check
15
- Checker.new.run
16
- end
17
- end
@@ -1,33 +0,0 @@
1
- require_relative "lib/rails_health_checker/version"
2
-
3
- Gem::Specification.new do |spec|
4
- spec.name = "rails-health-checker"
5
- spec.version = RailsHealthChecker::VERSION
6
- spec.authors = ["Arshdeep Singh"]
7
- spec.email = ["arsh199820@gmail.com"]
8
-
9
- spec.summary = "Comprehensive health checker for Rails applications and dependencies"
10
- spec.description = "A Ruby gem that provides comprehensive health checking for Rails applications, including database connectivity, gem dependencies, security vulnerabilities, and system health monitoring with a web dashboard."
11
- spec.homepage = "https://rails-health-checker.netlify.app"
12
- spec.license = "MIT"
13
- spec.required_ruby_version = ">= 2.6.0"
14
-
15
- spec.metadata["homepage_uri"] = "https://rails-health-checker.netlify.app"
16
- spec.metadata["source_code_uri"] = "https://github.com/ArshdeepGrover/rails-health-checker"
17
- spec.metadata["changelog_uri"] = "https://github.com/ArshdeepGrover/rails-health-checker/blob/main/CHANGELOG.md"
18
- spec.metadata["documentation_uri"] = "https://rails-health-checker.netlify.app"
19
- spec.metadata["bug_tracker_uri"] = "https://github.com/ArshdeepGrover/rails-health-checker/issues"
20
-
21
- spec.files = Dir.chdir(__dir__) do
22
- `git ls-files -z`.split("\x0").reject do |f|
23
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
24
- end
25
- end
26
- spec.bindir = "exe"
27
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
- spec.require_paths = ["lib"]
29
-
30
- spec.add_dependency "rails", ">= 6.0"
31
- spec.add_dependency "bundler", ">= 2.0"
32
- spec.add_development_dependency "rspec", "~> 3.0"
33
- end
data/simple_test.rb DELETED
@@ -1,52 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require_relative 'lib/rails_health_checker/version'
4
- require_relative 'lib/rails_health_checker/gem_analyzer'
5
-
6
- puts "=== Simple Gem Test ==="
7
- puts "Version: #{RailsHealthChecker::VERSION}"
8
-
9
- # Test gem analyzer with mocked Bundler
10
- module Bundler
11
- def self.load
12
- MockBundler.new
13
- end
14
- end
15
-
16
- class MockBundler
17
- def specs
18
- [
19
- MockGem.new('rails', '7.0.0'),
20
- MockGem.new('rspec', '3.12.0')
21
- ]
22
- end
23
- end
24
-
25
- class MockGem
26
- attr_reader :name, :version
27
-
28
- def initialize(name, version)
29
- @name = name
30
- @version = MockVersion.new(version)
31
- end
32
-
33
- def gem_dir
34
- "/path/to/#{name}"
35
- end
36
- end
37
-
38
- class MockVersion
39
- def initialize(version)
40
- @version = version
41
- end
42
-
43
- def to_s
44
- @version
45
- end
46
- end
47
-
48
- analyzer = RailsHealthChecker::GemAnalyzer.new
49
- results = analyzer.analyze
50
-
51
- puts "✓ Gem analysis: #{results[:total]} gems, #{results[:outdated]} outdated"
52
- puts "✅ Basic functionality works!"
data/test_gem.rb DELETED
@@ -1,100 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Simple test script to verify gem functionality
4
- require_relative 'lib/rails_health_checker'
5
-
6
- # Mock Rails and ActiveRecord for testing
7
- module Rails
8
- def self.version
9
- "7.0.0"
10
- end
11
- end
12
-
13
- module ActiveRecord
14
- class Base
15
- def self.connection
16
- MockConnection.new
17
- end
18
- end
19
- end
20
-
21
- class MockConnection
22
- def active?
23
- true
24
- end
25
- end
26
-
27
- class Time
28
- def self.current
29
- Time.now
30
- end
31
- end
32
-
33
- # Mock Bundler
34
- module Bundler
35
- def self.load
36
- MockBundler.new
37
- end
38
- end
39
-
40
- class MockBundler
41
- def specs
42
- [
43
- MockGem.new('rails', '7.0.0'),
44
- MockGem.new('rspec', '3.12.0')
45
- ]
46
- end
47
- end
48
-
49
- class MockGem
50
- attr_reader :name, :version
51
-
52
- def initialize(name, version)
53
- @name = name
54
- @version = MockVersion.new(version)
55
- end
56
-
57
- def gem_dir
58
- "/path/to/#{name}"
59
- end
60
- end
61
-
62
- class MockVersion
63
- def initialize(version)
64
- @version = version
65
- end
66
-
67
- def to_s
68
- @version
69
- end
70
- end
71
-
72
- # Test the gem
73
- puts "Testing RailsHealthChecker gem..."
74
-
75
- begin
76
- # Test version
77
- puts "✓ Version: #{RailsHealthChecker::VERSION}"
78
-
79
- # Test checker
80
- checker = RailsHealthChecker::Checker.new
81
- results = checker.run
82
- puts "✓ Health check completed"
83
-
84
- # Test gem analyzer
85
- analyzer = RailsHealthChecker::GemAnalyzer.new
86
- gem_results = analyzer.analyze
87
- puts "✓ Gem analysis completed: #{gem_results[:total]} gems found"
88
-
89
- # Test middleware
90
- middleware = RailsHealthChecker::HealthMiddleware.new(nil)
91
- env = { 'PATH_INFO' => '/health' }
92
- response = middleware.call(env)
93
- puts "✓ Health endpoint returns: #{response[0]} status"
94
-
95
- puts "\n✅ All tests passed!"
96
-
97
- rescue => e
98
- puts "❌ Test failed: #{e.message}"
99
- puts e.backtrace.first(3)
100
- end