Collector Installation
DBGorilla reads metrics from your infrastructure through the DBGorilla Collector. Wherever you
run it, the collector needs the same three things: a database login with the right grants, a
collector.toml, and outbound network access. This page covers all three. Pick your deployment
target from the pages that follow.
The collector reads PostgreSQL statistics directly and, for host statistics, talks to the Prometheus
node_exporter. You need one collector per network segment, and node_exporter on each database
host you want host metrics from.
On managed platforms like AWS RDS, where you have no access to the database host, the collector
reads equivalent metrics from CloudWatch and node_exporter is not required.
What the collector is
Section titled “What the collector is”The collector is a custom OpenTelemetry collector, shipped as a Docker image, that runs anywhere a Linux container runs. You configure it with a single file mounted into the container. The app shows you that file when you add a collector.
A collector reads from one or more components. A component is a logical database endpoint: a
single server, a cluster with readers and writers, or a cloud database endpoint. The collector must
be able to reach each component on the database port (5432 for PostgreSQL) and, for physical hosts,
the node_exporter port (9100 by default).
The collector needs outbound access to otlp.dbgorilla.com and auth.dbgorilla.com on port 443,
and nothing else. It listens on no inbound port. Metrics travel over the
OpenTelemetry Protocol (OTLP); management traffic uses the Open Agent
Management Protocol (OpAMP).
Database grants
Section titled “Database grants”Create a dedicated read-only login for the collector. “Read-only” is several grants, not one:
CREATE ROLE dbg_readonly LOGIN PASSWORD 'replace-me';GRANT pg_monitor TO dbg_readonly; -- cluster-wide statsGRANT USAGE ON SCHEMA public TO dbg_readonly; -- per schema you want capturedGRANT SELECT ON ALL TABLES IN SCHEMA public TO dbg_readonly;ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public GRANT SELECT ON TABLES TO dbg_readonly; -- tables created laterReplace app_owner with the role that creates your tables, and repeat the statement for each one.
ALTER DEFAULT PRIVILEGES without FOR ROLE covers only tables created by the role running it.
If your application creates tables as its own role and you ran the command as postgres, new
tables are not covered, and you land in the failure below the first time your application migrates.
List the roles that own tables with:
SELECT DISTINCT tableowner FROM pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema');CREATE ROLE and GRANT pg_monitor are cluster-wide, so run them once. The USAGE and SELECT
grants are not. They apply only to the database you are connected to and the schema you name, so
run them again for every database you list in databases, and once per schema inside it. Grant
them in one database only and you land in the failure below.
pg_monitor alone is not enough, and the failure is quiet: the collector connects and reports
metrics normally, then fails every schema capture with permission denied for table …, logged as
a warning that retries forever. The collector looks healthy and captures no schema at all. Schema
capture runs pg_dump, which must SELECT every table it reads.
pg_stat_statements
Section titled “pg_stat_statements”pg_stat_statements is required for full functionality. It is the PostgreSQL extension that
records how long each statement takes and how often it runs. Everything DBGorilla tells you about
query performance comes from it.
Without it, the collector still connects and still reports host metrics, database size, table statistics and cluster topology. What you lose is every query-level feature: slow query analysis, query-level recommendations, and anything that ranks statements by cost. The collector will not tell you this is missing once it is running, so check it up front:
SELECT * FROM pg_available_extensions WHERE name = 'pg_stat_statements';SHOW shared_preload_libraries;Loading it takes a full server restart, not a reload, because it hooks into the executor at
startup. One caution before you run it: ALTER SYSTEM SET replaces the whole value, it does not
append. Read the current setting first and include everything already there, or you will unload
another extension at the next restart.
SHOW shared_preload_libraries;-- if it is empty:ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements';-- if it already lists something, repeat every existing entry, for example:ALTER SYSTEM SET shared_preload_libraries = 'pg_cron,pg_stat_statements';
-- restart PostgreSQL, then:CREATE EXTENSION pg_stat_statements;On managed platforms you set it through the provider instead: a parameter group on AWS RDS and Aurora, server parameters on Azure Database for PostgreSQL, or database flags on Cloud SQL. Each still needs a restart.
Configuration
Section titled “Configuration”The example below runs one collector against one PostgreSQL cluster
(db-cluster1.internal.example.com), restricted to a single database.
The agent ID and secret are issued per collector; the tenant ID identifies your organization and is shared across all of its collectors. All three are shown when you add a collector in the app.
Keep secrets out of the file. Reference them as ${VAR} and supply the values as environment
variables, from whatever secrets manager you already use.
[dbgorilla]agent_id = "a8c1cde3-3e91-4ecf-b615-26bae0c35f02"tenant_id = "fd4c6676-c1a1-4d9a-babb-54958c26369d"secret = "${DBG_SERVER_SECRET}"
# One [[component]] block per database system to monitor.[[component]]name = "example_db" # the name your system appears under in DBGorillaengine = "postgres"
[component.provider]type = "self_hosted"
[component.auth]method = "password"user = "dbg_readonly"password = "${DB_PASSWORD}"
[component.connect]host = "db-cluster1.internal.example.com"port = 5432databases = ["example_db"] # empty = all non-template databasesssl_mode = "verify-full" # disable | require | verify-ca | verify-full
[commands]# Optional. When enabled, allows explain and execute_query (see below).enabled = true# allowed = ["explain"] # optional: further restrict to a subsetThe endpoints default to otlp.dbgorilla.com and auth.dbgorilla.com, so most configurations do
not set them at all.
Choosing ssl_mode
Section titled “Choosing ssl_mode”verify-full is the right choice whenever the database is reached over a network, and it works
against managed databases whose certificates chain to a public authority.
If your server presents a certificate from an internal authority, which is what most
Kubernetes-operator-managed PostgreSQL does, then verify-full and verify-ca fail on trust, because
the container has no reason to hold your CA. Either mount your CA into the container and point
ca_cert at it, or use require, which keeps the connection encrypted but skips certificate
verification.
Use disable only for a database on the same machine as the collector. Over a network it sends the
password and every query in clear text.
Commands
Section titled “Commands”The [commands] block is optional. When enabled, it lets the control plane run a fixed set of
read-oriented operations through the collector:
explain: plan-onlyEXPLAIN. NeverEXPLAIN ANALYZE; the query is not executed.execute_query: a singleSELECT, capped at 1,000 rows with a 30-second statement timeout.
Disable it and the collector cannot execute either. Anything that does run is still bounded by the privileges of the database user you configured. The collector cannot escalate beyond that user.