EctoCockroachExtras
Elixir library exposing CockroachDB cluster and database statistics for use from IEx,
scripts, or Phoenix.LiveDashboard.
It mimics the API of ecto_psql_extras, but
ecto_psql_extras doesn't work against CockroachDB: it depends on PostgreSQL internals
CockroachDB doesn't have (pg_stat_activity, pg_locks, pg_stat_statements, autovacuum),
and CockroachDB's pg_catalog compatibility shims for those are unpopulated stubs. This
library instead queries CockroachDB's own introspection surface: SHOW JOBS,
SHOW CHANGEFEED JOBS, SHOW STATISTICS, SHOW CLUSTER SETTINGS, and the
crdb_internal.* virtual tables.
Installation
def deps do
[
{:ecto_cockroach_extras, "~> 0.1.0"}
]
end
Usage
EctoCockroachExtras.jobs(MyApp.Repo)
EctoCockroachExtras.changefeed_jobs(MyApp.Repo)
EctoCockroachExtras.table_statistics(MyApp.Repo, "users")
EctoCockroachExtras.sessions(MyApp.Repo)
EctoCockroachExtras.running_queries(MyApp.Repo, args: [threshold: 5])
EctoCockroachExtras.locks(MyApp.Repo)
EctoCockroachExtras.contention(MyApp.Repo)
EctoCockroachExtras.cluster_settings(MyApp.Repo)
EctoCockroachExtras.cluster_settings(MyApp.Repo, args: [all: true, pattern: "sql.defaults%"])
EctoCockroachExtras.index_usage(MyApp.Repo)
EctoCockroachExtras.unused_indexes(MyApp.Repo)
EctoCockroachExtras.table_sizes(MyApp.Repo)
EctoCockroachExtras.index_sizes(MyApp.Repo)
EctoCockroachExtras.top_queries(MyApp.Repo)
EctoCockroachExtras.diagnose(MyApp.Repo, tables: ["users", "orders"])
By default an ASCII table is printed. Pass format: :raw to get the underlying
%Postgrex.Result{} instead:
EctoCockroachExtras.jobs(MyApp.Repo, format: :raw)
You can also run a query by name:
EctoCockroachExtras.query(:cluster_settings, MyApp.Repo, format: :raw)
SHOW CLUSTER SETTINGS
cluster_settings/2 wraps SHOW CLUSTER SETTINGS (public settings only) by default. Pass
args: [all: true] to switch to SHOW ALL CLUSTER SETTINGS, which also includes
non-public/internal settings and one extra public column. Pass args: [pattern: "..."]
to filter variable with a SQL LIKE pattern.
allow_unsafe_internals
A few crdb_internal.* virtual tables (locks, index_usage, unused_indexes) are gated
behind CockroachDB's allow_unsafe_internals session variable in production/CCL builds. The
SET and the query have to run on the same connection, so this library delegates them to your
repo. Define an unsafe_internals_query!/3 function on your Ecto repo that runs both in a
single transaction:
def unsafe_internals_query!(query, params, query_opts) do
transaction(fn ->
query!("SET allow_unsafe_internals = true", [], query_opts)
query!(query, params, query_opts)
end)
end
Just be aware these particular queries incur an extra round trip.
Phoenix.LiveDashboard
Phoenix.LiveDashboard's built-in Ecto Stats page picks an extras module from each repo's
adapter (Ecto.Adapters.Postgres -> EctoPSQLExtras, and so on). A CockroachDB repo reports
Ecto.Adapters.Postgres, so it would be routed to EctoPSQLExtras, whose PostgreSQL-only
queries don't work against CockroachDB.
Phoenix.LiveDashboard lets you override that per repo by listing it as a {repo, info_module}
tuple in :ecto_repos. EctoCockroachExtras implements the same API as EctoPSQLExtras, so
point your CockroachDB repo at it:
live_dashboard "/dashboard",
ecto_repos: [{MyApp.Repo, EctoCockroachExtras}]
Mixed setups work too - keep Postgres repos as bare modules and use a tuple only for the CockroachDB repo:
live_dashboard "/dashboard",
ecto_repos: [MyApp.PostgresRepo, {MyApp.CockroachRepo, EctoCockroachExtras}]
The {repo, info_module} form isn't on Hex yet (latest release is 0.8.7); until it ships,
depend on Phoenix.LiveDashboard from GitHub in your app's mix.exs:
{:phoenix_live_dashboard, github: "phoenixframework/phoenix_live_dashboard"}
What's not included
No CockroachDB equivalent, or lower priority for now: duplicate_indexes, records_rank,
table_foreign_keys, missing_fk_indexes, missing_fk_constraints, table_schema,
bloat, vacuum_stats, ssl_used, extensions, kill_all/cancel-session support, and
multi-node {repo, node} dispatch (all repo access is local-node only).
Testing
The test suite runs real queries against a live CockroachDB instance - nothing is mocked.
It defaults to localhost:26257 insecure; override with COCKROACH_HOST, COCKROACH_PORT,
COCKROACH_DATABASE, COCKROACH_USERNAME, COCKROACH_SSL env vars.
Start a local instance if you don't already have one running:
docker run -d --name crdb -p 26257:26257 cockroachdb/cockroach:v26.2.0 start-single-node --insecure
Then:
mix deps.get
mix test
License
MIT