Skip to content

Commit c278662

Browse files
authored
feat: collect database metrics (coder#17635)
Currently we don't have a way to get insight into Postgres connections being exhausted. By using the prometheus' [`DBStats` collector](https://github.com/prometheus/client_golang/blob/main/prometheus/collectors/dbstats_collector.go), we get some insight out-of-the-box. ``` # HELP go_sql_idle_connections The number of idle connections. # TYPE go_sql_idle_connections gauge go_sql_idle_connections{db_name="coder"} 1 # HELP go_sql_in_use_connections The number of connections currently in use. # TYPE go_sql_in_use_connections gauge go_sql_in_use_connections{db_name="coder"} 2 # HELP go_sql_max_idle_closed_total The total number of connections closed due to SetMaxIdleConns. # TYPE go_sql_max_idle_closed_total counter go_sql_max_idle_closed_total{db_name="coder"} 112 # HELP go_sql_max_idle_time_closed_total The total number of connections closed due to SetConnMaxIdleTime. # TYPE go_sql_max_idle_time_closed_total counter go_sql_max_idle_time_closed_total{db_name="coder"} 0 # HELP go_sql_max_lifetime_closed_total The total number of connections closed due to SetConnMaxLifetime. # TYPE go_sql_max_lifetime_closed_total counter go_sql_max_lifetime_closed_total{db_name="coder"} 0 # HELP go_sql_max_open_connections Maximum number of open connections to the database. # TYPE go_sql_max_open_connections gauge go_sql_max_open_connections{db_name="coder"} 10 # HELP go_sql_open_connections The number of established connections both in use and idle. # TYPE go_sql_open_connections gauge go_sql_open_connections{db_name="coder"} 3 # HELP go_sql_wait_count_total The total number of connections waited for. # TYPE go_sql_wait_count_total counter go_sql_wait_count_total{db_name="coder"} 28 # HELP go_sql_wait_duration_seconds_total The total time blocked waiting for a new connection. # TYPE go_sql_wait_duration_seconds_total counter go_sql_wait_duration_seconds_total{db_name="coder"} 0.086936235 ``` `go_sql_wait_count_total` is the metric I'm most interested in gaining, but the others are also very useful. Changing the prefix is easy (`prometheus.WrapRegistererWithPrefix`), but getting rid of the `go_` segment is not quite so easy. I've kept the changeset small for now. **NOTE:** I imported a library to determine the database name from the given conn string. It's [not as simple](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING) as one might hope. The database name is used for the `db_name` label. --------- Signed-off-by: Danny Kopping <dannykopping@gmail.com>
1 parent e718c3a commit c278662

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

cli/server.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,15 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
739739
_ = sqlDB.Close()
740740
}()
741741

742+
if options.DeploymentValues.Prometheus.Enable {
743+
// At this stage we don't think the database name serves much purpose in these metrics.
744+
// It requires parsing the DSN to determine it, which requires pulling in another dependency
745+
// (i.e. https://github.com/jackc/pgx), but it's rather heavy.
746+
// The conn string (https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING) can
747+
// take different forms, which make parsing non-trivial.
748+
options.PrometheusRegistry.MustRegister(collectors.NewDBStatsCollector(sqlDB, ""))
749+
}
750+
742751
options.Database = database.New(sqlDB)
743752
ps, err := pubsub.New(ctx, logger.Named("pubsub"), sqlDB, dbURL)
744753
if err != nil {

0 commit comments

Comments
 (0)