rails-health-checker 0.1.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.
@@ -0,0 +1,39 @@
1
+ module RailsHealthChecker
2
+ class GemAnalyzer
3
+ def analyze
4
+ gems = Bundler.load.specs
5
+ outdated = check_outdated_gems
6
+
7
+ {
8
+ total: gems.count,
9
+ outdated: outdated.count,
10
+ vulnerable: check_vulnerable_gems.count,
11
+ details: gem_details(gems, outdated)
12
+ }
13
+ end
14
+
15
+ private
16
+
17
+ def check_outdated_gems
18
+ `bundle outdated --parseable`.split("\n").map do |line|
19
+ line.split(" ")[0] if line.include?("(")
20
+ end.compact
21
+ end
22
+
23
+ def check_vulnerable_gems
24
+ # Simple check - in production, integrate with bundler-audit
25
+ []
26
+ end
27
+
28
+ def gem_details(gems, outdated)
29
+ gems.map do |gem|
30
+ {
31
+ name: gem.name,
32
+ version: gem.version.to_s,
33
+ outdated: outdated.include?(gem.name),
34
+ path: gem.gem_dir
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,53 @@
1
+ module RailsHealthChecker
2
+ class HealthMiddleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ if env['PATH_INFO'] == '/health'
9
+ health_check_response
10
+ else
11
+ @app.call(env)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def health_check_response
18
+ status = perform_quick_health_check
19
+
20
+ [
21
+ status[:code],
22
+ { 'Content-Type' => 'application/json' },
23
+ [status[:body].to_json]
24
+ ]
25
+ end
26
+
27
+ def perform_quick_health_check
28
+ begin
29
+ db_healthy = ActiveRecord::Base.connection.active?
30
+
31
+ {
32
+ code: 200,
33
+ body: {
34
+ status: 'healthy',
35
+ timestamp: Time.current.iso8601,
36
+ database: db_healthy ? 'connected' : 'disconnected',
37
+ rails_version: Rails.version,
38
+ ruby_version: RUBY_VERSION
39
+ }
40
+ }
41
+ rescue => e
42
+ {
43
+ code: 503,
44
+ body: {
45
+ status: 'unhealthy',
46
+ timestamp: Time.current.iso8601,
47
+ error: e.message
48
+ }
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,108 @@
1
+ module RailsHealthChecker
2
+ class JobAnalyzer
3
+ def analyze
4
+ {
5
+ sidekiq: analyze_sidekiq,
6
+ resque: analyze_resque,
7
+ active_job: analyze_active_job,
8
+ status: overall_job_status
9
+ }
10
+ end
11
+
12
+ private
13
+
14
+ def analyze_sidekiq
15
+ return { available: false } unless sidekiq_available?
16
+
17
+ stats = Sidekiq::Stats.new
18
+ {
19
+ available: true,
20
+ processed: stats.processed,
21
+ failed: stats.failed,
22
+ enqueued: stats.enqueued,
23
+ retry_size: stats.retry_size,
24
+ dead_size: stats.dead_size,
25
+ workers: stats.workers_size,
26
+ queues: queue_stats,
27
+ status: sidekiq_health_status(stats)
28
+ }
29
+ rescue => e
30
+ { available: true, error: "Sidekiq connection failed: #{e.message}", status: 'error' }
31
+ end
32
+
33
+ def analyze_resque
34
+ return { available: false } unless resque_available?
35
+
36
+ {
37
+ available: true,
38
+ pending: Resque.info[:pending],
39
+ processed: Resque.info[:processed],
40
+ failed: Resque.info[:failed],
41
+ workers: Resque.info[:workers],
42
+ working: Resque.info[:working],
43
+ queues: Resque.queues.size,
44
+ status: resque_health_status
45
+ }
46
+ rescue => e
47
+ { available: true, error: "Resque connection failed: #{e.message}", status: 'error' }
48
+ end
49
+
50
+ def analyze_active_job
51
+ return { available: false } unless active_job_available?
52
+
53
+ {
54
+ available: true,
55
+ adapter: ActiveJob::Base.queue_adapter.class.name,
56
+ status: 'healthy'
57
+ }
58
+ rescue => e
59
+ { available: true, error: e.message, status: 'error' }
60
+ end
61
+
62
+ def sidekiq_available?
63
+ defined?(Sidekiq)
64
+ end
65
+
66
+ def resque_available?
67
+ defined?(Resque)
68
+ end
69
+
70
+ def active_job_available?
71
+ defined?(ActiveJob)
72
+ end
73
+
74
+ def queue_stats
75
+ return {} unless sidekiq_available?
76
+
77
+ Sidekiq::Queue.all.map do |queue|
78
+ {
79
+ name: queue.name,
80
+ size: queue.size,
81
+ latency: queue.latency.round(2)
82
+ }
83
+ end
84
+ end
85
+
86
+ def sidekiq_health_status(stats)
87
+ return 'critical' if stats.failed > 100
88
+ return 'warning' if stats.enqueued > 1000 || stats.retry_size > 50
89
+ 'healthy'
90
+ end
91
+
92
+ def resque_health_status
93
+ return 'critical' if Resque.info[:failed] > 100
94
+ return 'warning' if Resque.info[:pending] > 1000
95
+ 'healthy'
96
+ end
97
+
98
+ def overall_job_status
99
+ statuses = []
100
+ statuses << analyze_sidekiq[:status] if sidekiq_available?
101
+ statuses << analyze_resque[:status] if resque_available?
102
+
103
+ return 'critical' if statuses.include?('critical') || statuses.include?('error')
104
+ return 'warning' if statuses.include?('warning')
105
+ statuses.empty? ? 'not_configured' : 'healthy'
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,11 @@
1
+ module RailsHealthChecker
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load "rails_health_checker/tasks.rb"
5
+ end
6
+
7
+ initializer "rails_health_checker.add_middleware" do |app|
8
+ app.middleware.use RailsHealthChecker::DashboardMiddleware
9
+ end
10
+ end
11
+ end