Upcheck
Upcheck is a zero-dependency Ruby gem for reading the public status of third-party services. Use it to show degradation banners, fail fast in background jobs, or fall back to another provider when a dependency is down.
The entry point is Upcheck.for(:provider), which reads like a sentence:
Upcheck.for(:anthropic).operational? # => true
Upcheck.for(:openai).incidents # => [#<Upcheck::Incident ...>]
Upcheck.for(:github).component("Git Operations").operational?
[!NOTE] Upcheck supports any service that publishes a public Atlassian Statuspage v2 API (the majority of SaaS status pages), plus Heroku's own status format. More non-Statuspage adapters can be added behind the same interface.
Installation
Add to your Gemfile:
bundle add upcheck
Or install it manually:
gem install upcheck
Upcheck requires Ruby 3.2+ and has no runtime dependencies beyond the standard library.
Quick start
require "upcheck"
provider = Upcheck.for(:anthropic)
# Boolean query methods (primary interface)
provider.operational? # => true when the provider reports no incidents
provider.degraded? # => true for minor degradation
provider.major_outage? # => true for major or critical outages
provider.maintenance? # => true when the page is in a planned maintenance window
# Raw indicator string, useful for logging or serialization
provider.status # => "none" | "minor" | "major" | "critical" | "maintenance"
provider.description # => "All Systems Operational"
# Components
provider.components # => [#<Upcheck::Component name="Claude API", ...>, ...]
api = provider.component("Claude API") # returns nil if no component by that name
api.operational? # => false
api.status # => "degraded_performance"
# Active incidents
incident = provider.incidents.first
incident.name # => "Elevated error rates on ..."
incident.impact # => "minor"
incident.updates.last.body
# Active scheduled maintenances (same shape as incidents)
provider.scheduled_maintenances
Each provider object caches the JSON it fetches, so repeat calls to operational?, components, etc. on the same provider don't re-hit the network. Build a new provider with Upcheck.for(...) when you want fresh data.
Configuration
Upcheck.configure do |config|
config.http_timeout = 3
config.register_provider(:my_saas) { Upcheck::Adapters::Statuspage.new("https://status.my-saas.example.com") }
end
| Option | Default | Description |
|---|---|---|
http_timeout |
5 |
Seconds to wait for both open and read on each HTTP request. |
register_provider(name, &block) |
(none) | Registers a provider. The block is called on each Upcheck.for(name) and must return an adapter instance (e.g., Upcheck::Adapters::Statuspage.new(url), Upcheck::Adapters::Heroku.new, or your own). Overrides built-ins when the name matches. |
Custom adapters
If your target doesn't speak Statuspage and isn't one of the built-ins, write an adapter class that satisfies Upcheck's five-method contract and register it:
class MyAdapter
def status # => "none" | "minor" | "major" | "critical" | "maintenance"
def description # => String, a human-readable summary
def components # => Array<Upcheck::Component>
def incidents # => Array<Upcheck::Incident>
def scheduled_maintenances # => Array<Upcheck::Incident>
end
Upcheck.configure do |config|
config.register_provider(:my_service) { MyAdapter.new(...) }
end
Upcheck.for(:my_service).operational?
lib/upcheck/adapters/heroku.rb is a real-world example — it translates
Heroku's per-system colors and incident format into Upcheck's canonical shape.
Built-in providers
Upcheck ships with a registry of well-known providers so you can reference them by symbol:
| Symbol | URL |
|---|---|
:anthropic |
https://status.claude.com |
:openai |
https://status.openai.com |
:github |
https://www.githubstatus.com |
:twilio |
https://status.twilio.com |
:datadog |
https://status.datadoghq.com |
:rubygems |
https://status.rubygems.org |
:cloudflare |
https://www.cloudflarestatus.com |
:discord |
https://discordstatus.com |
:digitalocean |
https://status.digitalocean.com |
:vercel |
https://www.vercel-status.com |
:stripe |
https://www.stripestatus.com |
:shopify |
https://www.shopifystatus.com |
:sentry |
https://status.sentry.io |
:heroku |
https://status.heroku.com |
Missing one? Register it at runtime. Any service hosted on Atlassian Statuspage works out of the box; other formats need a custom adapter.
Upcheck.configure do |config|
config.register_provider(:my_saas) { Upcheck::Adapters::Statuspage.new("https://status.my-saas.example.com") }
end
Upcheck.for(:my_saas).operational?
Errors
Every failure raises a specific subclass of Upcheck::Error:
| Exception | When it's raised |
|---|---|
Upcheck::UnknownProviderError |
Upcheck.for(:name) was called with a provider that isn't registered. |
Upcheck::TimeoutError |
The HTTP request exceeded http_timeout. |
Upcheck::ConnectionError |
DNS failure, refused connection, unreachable host. |
Upcheck::HTTPError |
The server returned a non-success response (4xx, 5xx, or too many redirects). #status holds the HTTP code. |
Upcheck::ParseError |
The body wasn't valid JSON. |
Upcheck::TransportError |
Parent of TimeoutError, ConnectionError, and HTTPError. Rescue this to catch any transport failure. |
Development
After checking out the repo, run bin/setup to install dependencies. Then, run bundle exec rspec to run the tests.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/MatheusRich/upcheck.
- Fork the repository.
- Create a topic branch (
git checkout -b my-new-feature). - Add tests for your change and make them pass (
bundle exec rspec). - Commit (
git commit -am "Add my new feature"). - Push (
git push origin my-new-feature). - Open a pull request.
License
The gem is available as open source under the terms of the MIT License.