rails_health_checks 0.6.0 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 010ea2d8734800da5baaaa805b0671ac685f3c5a26a11967ca64f00cfd03500c
4
- data.tar.gz: 7f81bbd9940d17d7b67f779da47b6fe42796ab6542080fcf2a790976c9e83be5
3
+ metadata.gz: cf33a3b43064f931e789b7d28fff6145c206229b14da15d4da208717007f2c44
4
+ data.tar.gz: 85c221c95529597327d5a830c9dc6f46da3720133cc19b2366be7af3256f0f57
5
5
  SHA512:
6
- metadata.gz: f6da67674aa9871b760450a01834a09b1bdebcbacbd21c330c60d2a6c98725b331321c3e187e7741269f414b11562b1dcb48ea99ec8d8face847677c678bbdd0
7
- data.tar.gz: f5cf9df5e54de04defd67440c8d838f7c7a085f2712351b1e79920975d64d5c957c43d02cf5de3497ef25ae4ee77ac8a6d8e52d32c682fb0158e753d958a683b
6
+ metadata.gz: 5f460a617a378811cceda76d3993f589424af6b8bca336a00f2e887cdcc540f1bf29a6a0f049dd7a1a19c8944efff566f92e567a70380651983ed95e106abaa3
7
+ data.tar.gz: ec5f9be2fc4ad1d84582006455cb742c010232b4e65c0f99f8d4782429d48bda9973e0f6f9e9074bc1d799a03b5e856daf650adc8c0b2dda4637242a7844ede9
data/README.md CHANGED
@@ -57,6 +57,8 @@ mount RailsHealthChecks::Engine => "/health"
57
57
  | `GET /health/live` | Plain text | Load balancer liveness probes |
58
58
  | `GET /health/metrics` | Prometheus text | Prometheus / OpenMetrics scraping |
59
59
 
60
+ `/health` and `/health/live` also respond to `HEAD` requests (useful for lightweight load balancer probes).
61
+
60
62
  HTTP status is `200 OK` when all checks pass, `503 Service Unavailable` otherwise (except `/metrics` which always returns `200`).
61
63
 
62
64
  ### JSON response shape
@@ -82,11 +84,14 @@ Status values: `ok` | `degraded` | `critical`. Overall status is `critical` if a
82
84
  ```ruby
83
85
  # config/initializers/rails_health_checks.rb
84
86
  RailsHealthChecks.configure do |config|
85
- config.checks = [:database, :cache] # checks to run (default: [:database])
86
- config.timeout = 5 # global timeout per check in seconds (default: 5)
87
+ config.checks = [:database, :cache] # checks to run (default: [:database])
88
+ config.timeout = 5 # global timeout per check in seconds (default: 5)
89
+ config.cache_duration = 10 # cache results for N seconds (default: nil, disabled)
87
90
  end
88
91
  ```
89
92
 
93
+ Configuration is validated at boot time. An unknown check name or a missing `http_url` for the `:http` check raises `RailsHealthChecks::ConfigurationError` on startup rather than silently failing on the first request.
94
+
90
95
  [↑ Back to top](#table-of-contents)
91
96
 
92
97
  ---
@@ -139,7 +144,7 @@ The block receives the `ActionDispatch::Request` object and must return a truthy
139
144
  | `:resque` | Resque Redis connectivity; optional `config.resque_queue_size` threshold for total queue depth |
140
145
  | `:disk` | Free disk bytes via `df`; optional `config.disk_warn_threshold` / `config.disk_critical_threshold` (bytes) and `config.disk_path` (default: `/`) |
141
146
  | `:memory` | Process RSS via `ps`; optional `config.memory_threshold` (bytes) reports `degraded` when exceeded |
142
- | `:http` | HTTP GET to `config.http_url`; reports `critical` if response code differs from `config.http_expected_status` (default: `200`) or a network error occurs |
147
+ | `:http` | HTTP GET to `config.http_url`; reports `critical` if response code differs from `config.http_expected_status` (default: `200`) or a network error occurs; optional `config.http_headers` hash sends custom request headers (e.g. `{ "Authorization" => "Bearer ..." }`) |
143
148
 
144
149
  [↑ Back to top](#table-of-contents)
145
150
 
@@ -9,6 +9,18 @@ module RailsHealthChecks
9
9
 
10
10
  def run_checks(check_names)
11
11
  config = RailsHealthChecks.configuration
12
+
13
+ if config.cache_duration
14
+ cache_key = check_names.map(&:to_s).sort.join(",")
15
+ RailsHealthChecks.result_cache.fetch(cache_key, ttl: config.cache_duration) do
16
+ build_and_run(check_names, config)
17
+ end
18
+ else
19
+ build_and_run(check_names, config)
20
+ end
21
+ end
22
+
23
+ def build_and_run(check_names, config)
12
24
  checks = CheckRegistry.build(check_names)
13
25
  CheckRegistry.run(checks, timeout: config.timeout)
14
26
  end
data/config/routes.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RailsHealthChecks::Engine.routes.draw do
4
- get "/", to: "health#show", as: :health
5
- get "/live", to: "live#show", as: :health_live
4
+ match "/", to: "health#show", as: :health, via: [:get, :head]
5
+ match "/live", to: "live#show", as: :health_live, via: [:get, :head]
6
6
  get "/metrics", to: "metrics#show", as: :health_metrics
7
7
  get "/:id", to: "groups#show", as: :health_group
8
8
  end
@@ -15,7 +15,8 @@ module RailsHealthChecks
15
15
  memory: -> { Checks::MemoryCheck.new(threshold: RailsHealthChecks.configuration.memory_threshold) },
16
16
  http: -> { Checks::HttpCheck.new(
17
17
  url: RailsHealthChecks.configuration.http_url,
18
- expected_status: RailsHealthChecks.configuration.http_expected_status
18
+ expected_status: RailsHealthChecks.configuration.http_expected_status,
19
+ headers: RailsHealthChecks.configuration.http_headers
19
20
  ) },
20
21
  disk: -> { Checks::DiskCheck.new(
21
22
  warn_threshold: RailsHealthChecks.configuration.disk_warn_threshold,
@@ -6,14 +6,18 @@ require "uri"
6
6
  module RailsHealthChecks
7
7
  module Checks
8
8
  class HttpCheck < Check
9
- def initialize(url:, expected_status: 200)
9
+ def initialize(url:, expected_status: 200, headers: {})
10
10
  @url = url
11
11
  @expected_status = expected_status
12
+ @headers = headers
12
13
  end
13
14
 
14
15
  def call
15
16
  measure do
16
- response = Net::HTTP.get_response(URI.parse(@url))
17
+ uri = URI.parse(@url)
18
+ request = Net::HTTP::Get.new(uri)
19
+ @headers.each { |name, value| request[name] = value }
20
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(request) }
17
21
  code = response.code.to_i
18
22
  return fail_with("HTTP GET #{@url} returned #{code}, expected #{@expected_status}") if code != @expected_status
19
23
  end
@@ -1,16 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsHealthChecks
4
+ class ConfigurationError < StandardError; end
5
+
4
6
  class Configuration
7
+ BUILT_IN_NAMES = %i[database cache sidekiq solid_queue good_job resque disk memory http].freeze
8
+
5
9
  attr_writer :checks
6
- attr_accessor :timeout, :allowed_ips, :token, :sidekiq_queue_size, :solid_queue_job_count, :good_job_latency,
10
+ attr_accessor :timeout, :cache_duration, :allowed_ips, :token,
11
+ :sidekiq_queue_size, :solid_queue_job_count, :good_job_latency,
7
12
  :resque_queue_size, :disk_warn_threshold, :disk_critical_threshold, :disk_path,
8
- :memory_threshold, :http_url, :http_expected_status
13
+ :memory_threshold, :http_url, :http_expected_status, :http_headers
9
14
  attr_reader :authenticate_block, :custom_checks, :groups
10
15
 
11
16
  def initialize
12
17
  @checks = [:database]
13
18
  @timeout = 5
19
+ @cache_duration = nil
14
20
  @allowed_ips = nil
15
21
  @token = nil
16
22
  @authenticate_block = nil
@@ -24,6 +30,7 @@ module RailsHealthChecks
24
30
  @memory_threshold = nil
25
31
  @http_url = nil
26
32
  @http_expected_status = 200
33
+ @http_headers = {}
27
34
  @custom_checks = {}
28
35
  @groups = {}
29
36
  @disabled_checks = {}
@@ -53,5 +60,18 @@ module RailsHealthChecks
53
60
  @custom_checks[name] = check
54
61
  @checks << name unless @checks.include?(name)
55
62
  end
63
+
64
+ def validate!
65
+ all_checks = @checks + @groups.values.flatten
66
+ all_checks.uniq.each do |name|
67
+ next if BUILT_IN_NAMES.include?(name) || @custom_checks.key?(name)
68
+
69
+ raise ConfigurationError, "Unknown check :#{name}. Built-ins: #{BUILT_IN_NAMES.join(', ')}"
70
+ end
71
+
72
+ if @checks.include?(:http) && @http_url.nil?
73
+ raise ConfigurationError, "config.checks includes :http but config.http_url is not set"
74
+ end
75
+ end
56
76
  end
57
77
  end
@@ -4,5 +4,9 @@ module RailsHealthChecks
4
4
  class Engine < ::Rails::Engine
5
5
  isolate_namespace RailsHealthChecks
6
6
  config.generators.api_only = true
7
+
8
+ config.after_initialize do
9
+ RailsHealthChecks.configuration.validate!
10
+ end
7
11
  end
8
12
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsHealthChecks
4
+ class ResultCache
5
+ def initialize
6
+ @store = {}
7
+ @mutex = Mutex.new
8
+ end
9
+
10
+ def fetch(key, ttl:)
11
+ @mutex.synchronize do
12
+ entry = @store[key]
13
+ return entry[:results] if entry && (Process.clock_gettime(Process::CLOCK_MONOTONIC) - entry[:at]) < ttl
14
+
15
+ results = yield
16
+ @store[key] = { results: results, at: Process.clock_gettime(Process::CLOCK_MONOTONIC) }
17
+ results
18
+ end
19
+ end
20
+
21
+ def clear
22
+ @mutex.synchronize { @store.clear }
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsHealthChecks
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
@@ -17,6 +17,7 @@ require "rails_health_checks/checks/http_check"
17
17
  require "rails_health_checks/check_registry"
18
18
  require "rails_health_checks/response_builder"
19
19
  require "rails_health_checks/prometheus_formatter"
20
+ require "rails_health_checks/result_cache"
20
21
 
21
22
  module RailsHealthChecks
22
23
  class << self
@@ -27,5 +28,9 @@ module RailsHealthChecks
27
28
  def configuration
28
29
  @configuration ||= Configuration.new
29
30
  end
31
+
32
+ def result_cache
33
+ @result_cache ||= ResultCache.new
34
+ end
30
35
  end
31
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_health_checks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuck Smith
@@ -60,6 +60,7 @@ files:
60
60
  - lib/rails_health_checks/engine.rb
61
61
  - lib/rails_health_checks/prometheus_formatter.rb
62
62
  - lib/rails_health_checks/response_builder.rb
63
+ - lib/rails_health_checks/result_cache.rb
63
64
  - lib/rails_health_checks/version.rb
64
65
  - lib/tasks/rails_health_checks_tasks.rake
65
66
  homepage: https://github.com/eclectic-coding/rails_health_checks