# Sanito

A Plug health-check endpoint with isolated, time-limited plugin checks.

## Installation

```elixir
def deps do
  [
    {:sanito, "~> 0.2.0"}
  ]
end
```

The Ecto plugin also requires `{:ecto_sql, "~> 3.13"}`.

## Usage

Add Sanito before your router:

```elixir
defmodule MyAppWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :my_app

  plug Sanito.Plug,
    path: "/health",
    timeout: 5_000,
    plugins: [
      {Sanito.Plugins.EctoPlugin, repo: MyApp.Repo},
      MyApp.Health.CachePlugin
    ]

  plug MyAppWeb.Router
end
```

| Option | Default | Description |
| --- | --- | --- |
| `:path` | `"/health"` | Health-check path. |
| `:plugins` | `[]` | Modules or `{module, keyword_options}` entries. |
| `:timeout` | `5_000` | Timeout for each plugin, in milliseconds. |

Sanito returns `200` when every check succeeds and `503` when any check fails.

## Custom plugins

Plugins implement `Sanito.PluginBehaviour` and return `{:ok, message}` or
`{:error, message}` with a string message.

```elixir
defmodule MyApp.Health.CachePlugin do
  @behaviour Sanito.PluginBehaviour

  @impl true
  def check(_conn, opts) do
    name = Keyword.get(opts, :name, "cache")
    {:ok, "#{name} is available"}
  end
end
```

Plugin error messages are public. Exceptions, exits, malformed results, and Ecto errors
return generic messages while details are written to application logs.

The Ecto plugin runs `SELECT 1` against its configured repo:

```elixir
plugins: [{Sanito.Plugins.EctoPlugin, repo: MyApp.Repo}]
```

## Development

```shell
MIX_ENV=test mix ci
```

Sanito is available under the [MIT License](LICENSE).
