TowerDB
A Tower reporter that stores errors and exceptions in a PostgreSQL database using Ecto.
Warning
Not production ready. TowerDB is under active development and its API may still change. We use it in several applications at Mimiquate, but it hasn't yet reached the bar we'd consider production ready. Use it at your own risk.
Features we're waiting on before calling it production ready:
- Performance test
Installation
Add tower_db to your list of dependencies in mix.exs:
def deps do
[
{:tower_db, "~> 0.9.0"}
]
end
Then fetch the dependencies:
mix deps.get
Setup
Add TowerDB to your Tower reporters:
# config/config.exs
config(
:tower,
:reporters,
[
# along any other possible reporters
TowerDB
]
)
And configure :tower_db.
# config/runtime.exs
if config_env() == :prod do
config :tower_db,
enabled: true,
repo: MyApp.Repo
end
TowerDB requires database tables to store error events. Generate an Ecto migration:
mix ecto.gen.migration add_tower_db
If you want to use a repo different from MyApp.Repo as its primary repo, specify it with the -r flag:
mix ecto.gen.migration add_tower_db -r MyApp.SecondaryRepo
Then add the following content to the generated migration file:
defmodule MyApp.Repo.Migrations.AddTowerDB do
use Ecto.Migration
def up, do: TowerDB.Migration.up(from: 0, to: 8)
def down, do: TowerDB.Migration.down(from: 8, to: 0)
end
Run the migration:
mix ecto.migrate
Reporting
That's it. There's no extra source code needed to get reports in your database.
Tower will automatically report any errors (exceptions, throws or abnormal exits) occurring in your application. That includes errors in any plug call (including Phoenix), Oban jobs, async task or any other Elixir process.
You can also enable or disable the reporter at runtime:
TowerDB.disable()
TowerDB.enable()
Pruner
TowerDB can automatically delete old or excess events so storage stays bounded. It's enabled by default with the settings below; configure :pruner under :tower_db to change that:
# config/config.exs
# enabled with defaults (same as not setting :pruner at all)
config :tower_db, pruner: []
# enabled, overriding only the settings you name (the rest keep their defaults)
config :tower_db, pruner: [max_age: {30, :days}]
# disabled entirely
config :tower_db, pruner: false
Available settings, all optional:
| key | meaning | default |
|---|---|---|
max_age |
how long an event is kept before deletion | {90, :days} |
max_size |
total events kept across all issues | 100_000 |
max_size_per_issue |
events kept per issue | 1_000 |
interval |
time between prune runs | {30, :seconds} |
batch_size |
max rows deleted per batch | 1_000 |
max_age and interval are {amount, unit} tuples, with unit one of :seconds, :minutes, :hours, or :days.
max_age, max_size and max_size_per_issue accept :infinity to disable that specific check.
Each prune run deletes, in batches of batch_size:
- events older than
max_age(unless:infinity); - for each issue, the oldest events beyond
max_size_per_issue(unless:infinity); - the oldest events beyond
max_sizeoverall (unless:infinity).
License
See LICENSE.