diff --git a/docs/generated/metrics/metrics.html b/docs/generated/metrics/metrics.html index 89ab705bafac..9c347f34d101 100644 --- a/docs/generated/metrics/metrics.html +++ b/docs/generated/metrics/metrics.html @@ -1570,6 +1570,7 @@ APPLICATIONsql.savepoint.started.countNumber of SQL SAVEPOINT statements startedSQL StatementsCOUNTERCOUNTAVGNON_NEGATIVE_DERIVATIVE APPLICATIONsql.savepoint.started.count.internalNumber of SQL SAVEPOINT statements started (internal queries)SQL Internal StatementsCOUNTERCOUNTAVGNON_NEGATIVE_DERIVATIVE APPLICATIONsql.schema.invalid_objectsGauge of detected invalid objects within the system.descriptor table (measured by querying crdb_internal.invalid_objects)ObjectsGAUGECOUNTAVGNONE +APPLICATIONsql.schema_changer.object_countCounter of the number of objects in the clusterObjectsGAUGECOUNTAVGNONE APPLICATIONsql.schema_changer.permanent_errorsCounter of the number of permanent errors experienced by the schema changerErrorsCOUNTERCOUNTAVGNON_NEGATIVE_DERIVATIVE APPLICATIONsql.schema_changer.retry_errorsCounter of the number of retriable errors experienced by the schema changerErrorsCOUNTERCOUNTAVGNON_NEGATIVE_DERIVATIVE APPLICATIONsql.schema_changer.runningGauge of currently running schema changesSchema changesGAUGECOUNTAVGNONE diff --git a/pkg/sql/catalog/descs/collection.go b/pkg/sql/catalog/descs/collection.go index ea37b462cc0c..b120845b9ffd 100644 --- a/pkg/sql/catalog/descs/collection.go +++ b/pkg/sql/catalog/descs/collection.go @@ -218,6 +218,23 @@ func (tc *Collection) HasUncommittedDescriptors() bool { return tc.uncommitted.uncommitted.Len() > 0 } +// HasUncommittedNewOrDroppedDescriptors returns true if the collection contains +// any uncommitted descriptors that are newly created or dropped. +func (tc *Collection) HasUncommittedNewOrDroppedDescriptors() bool { + isNewDescriptor := false + err := tc.uncommitted.iterateUncommittedByID(func(desc catalog.Descriptor) error { + if desc.GetVersion() == 1 || desc.Dropped() { + isNewDescriptor = true + return iterutil.StopIteration() + } + return nil + }) + if err != nil { + return false + } + return isNewDescriptor +} + // HasUncommittedTypes returns true if the Collection contains uncommitted // types. func (tc *Collection) HasUncommittedTypes() (has bool) { diff --git a/pkg/sql/conn_executor.go b/pkg/sql/conn_executor.go index 0a19c899d529..73093c0030df 100644 --- a/pkg/sql/conn_executor.go +++ b/pkg/sql/conn_executor.go @@ -4028,7 +4028,12 @@ func (ex *connExecutor) txnStateTransitionsApplyWrapper( }(); err != nil { return ai, err } - + if ex.extraTxnState.descCollection.HasUncommittedNewOrDroppedDescriptors() { + execCfg := ex.planner.ExecCfg() + if err := UpdateDescriptorCount(ex.Ctx(), execCfg, execCfg.SchemaChangerMetrics); err != nil { + log.Warningf(ex.Ctx(), "failed to scan descriptor table: %v", err) + } + } fallthrough case txnRollback: ex.resetExtraTxnState(ex.Ctx(), advInfo.txnEvent, payloadErr) diff --git a/pkg/sql/isql/isql_db.go b/pkg/sql/isql/isql_db.go index fb60ce68e89d..9d8ffaf91d71 100644 --- a/pkg/sql/isql/isql_db.go +++ b/pkg/sql/isql/isql_db.go @@ -87,7 +87,7 @@ type Executor interface { ) (int, error) // QueryRow executes the supplied SQL statement and returns a single row, or - // nil if no row is found, or an error if more that one row is returned. + // nil if no row is found, or an error if more than one row is returned. // // QueryRow is deprecated. Use QueryRowEx() instead. QueryRow( diff --git a/pkg/sql/schema_changer.go b/pkg/sql/schema_changer.go index 74a3c35486e6..22c8bf69db69 100644 --- a/pkg/sql/schema_changer.go +++ b/pkg/sql/schema_changer.go @@ -3341,3 +3341,20 @@ func (p *planner) CanCreateCrossDBSequenceRef() error { } return nil } + +// UpdateDescriptorCount updates our sql.schema_changer.object_count gauge with +// a fresh count of objects in the system.descriptor table. +func UpdateDescriptorCount( + ctx context.Context, execCfg *ExecutorConfig, metric *SchemaChangerMetrics, +) error { + return DescsTxn(ctx, execCfg, func(ctx context.Context, txn isql.Txn, col *descs.Collection) error { + row, err := txn.QueryRow(ctx, "sql-schema-changer-object-count", txn.KV(), + `SELECT count(*) FROM system.descriptor`) + if err != nil { + return err + } + count := *row[0].(*tree.DInt) + metric.ObjectCount.Update(int64(count)) + return nil + }) +} diff --git a/pkg/sql/schema_changer_metrics.go b/pkg/sql/schema_changer_metrics.go index 4356c382f614..e1c78a00059f 100644 --- a/pkg/sql/schema_changer_metrics.go +++ b/pkg/sql/schema_changer_metrics.go @@ -38,6 +38,12 @@ var ( Measurement: "Errors", Unit: metric.Unit_COUNT, } + metaObjects = metric.Metadata{ + Name: "sql.schema_changer.object_count", + Help: "Counter of the number of objects in the cluster", + Measurement: "Objects", + Unit: metric.Unit_COUNT, + } ) // SchemaChangerMetrics are metrics corresponding to the schema changer. @@ -48,6 +54,7 @@ type SchemaChangerMetrics struct { PermanentErrors *metric.Counter ConstraintErrors telemetry.Counter UncategorizedErrors telemetry.Counter + ObjectCount *metric.Gauge } // MetricStruct makes SchemaChangerMetrics a metric.Struct. @@ -64,5 +71,6 @@ func NewSchemaChangerMetrics() *SchemaChangerMetrics { PermanentErrors: metric.NewCounter(metaPermanentErrors), ConstraintErrors: sqltelemetry.SchemaChangeErrorCounter("constraint_violation"), UncategorizedErrors: sqltelemetry.SchemaChangeErrorCounter("uncategorized"), + ObjectCount: metric.NewGauge(metaObjects), } }