def _collect_stats(
        self,
        key,
        db,
        instance_tags,
        relations,
        custom_metrics,
        collect_function_metrics,
        collect_count_metrics,
        collect_activity_metrics,
        collect_database_size_metrics,
        collect_default_db,
        interface_error,
        programming_error,
    ):
        """Query pg_stat_* for various metrics
        If relations is not an empty list, gather per-relation metrics
        on top of that.
        If custom_metrics is not an empty list, gather custom metrics defined in postgres.yaml
        """

        db_instance_metrics = self._get_instance_metrics(key, db, collect_database_size_metrics, collect_default_db)
        bgw_instance_metrics = self._get_bgw_metrics(key, db)
        archiver_instance_metrics = self._get_archiver_metrics(key, db)

        metric_scope = [self.CONNECTION_METRICS, self.LOCK_METRICS]

        if collect_function_metrics:
            metric_scope.append(self.FUNCTION_METRICS)
        if collect_count_metrics:
            metric_scope.append(self.COUNT_METRICS)

        # Do we need relation-specific metrics?
        relations_config = {}
        if relations:
            metric_scope += [self.REL_METRICS, self.IDX_METRICS, self.SIZE_METRICS, self.STATIO_METRICS]
            relations_config = self._build_relations_config(relations)

        replication_metrics = self._get_replication_metrics(key, db)
        if replication_metrics is not None:
            # FIXME: constants shouldn't be modified
            self.REPLICATION_METRICS['metrics'] = replication_metrics
            metric_scope.append(self.REPLICATION_METRICS)

        try:
            cursor = db.cursor()
            results_len = self._query_scope(
                cursor, db_instance_metrics, key, db, instance_tags, False, programming_error, relations_config
            )
            if results_len is not None:
                self.gauge(
                    "postgresql.db.count", results_len, tags=[t for t in instance_tags if not t.startswith("db:")]
                )

            self._query_scope(
                cursor, bgw_instance_metrics, key, db, instance_tags, False, programming_error, relations_config
            )
            self._query_scope(
                cursor, archiver_instance_metrics, key, db, instance_tags, False, programming_error, relations_config
            )

            if collect_activity_metrics:
                activity_metrics = self._get_activity_metrics(key, db)
                self._query_scope(
                    cursor, activity_metrics, key, db, instance_tags, False, programming_error, relations_config
                )

            for scope in list(metric_scope) + custom_metrics:
                self._query_scope(
                    cursor, scope, key, db, instance_tags, scope in custom_metrics, programming_error, relations_config
                )

            cursor.close()
        except (interface_error, socket.error) as e:
            self.log.error("Connection error: %s" % str(e))
            raise ShouldRestartException