Read queue depths with Find, not Scan (closes #234) (#237)
Some checks failed
check / check (push) Superseded by a newer commit; never tested

Both queue-depth reads used (*gorm.DB).Scan, which swaps GORM's own trace
recorder in for the logging adapter. That recorder does not implement
gorm.ParamsFilter, so those statements logged their bound values
interpolated, bypassing the suppression added for #207.

The scan guard from #222 and the queue-depth sampler from #224 each gated
green against a next that lacked the other; both landed and next went red.

Converted to Find. The emitted SQL is identical apart from placeholders,
and both paths parse the anonymous dest schema the same way, so the
queue-depth gauges are unchanged.
This commit was merged in pull request #237.
This commit is contained in:
2026-08-20 07:55:20 +02:00
parent aba02bc509
commit 89b2dadd48
3 changed files with 206 additions and 5 deletions

View File

@@ -95,6 +95,8 @@ func (e *Engine) sampleQueueDepths(ctx context.Context) {
// targetTypesByID maps every configured target id to its type. The
// deliveries live in the per-webhook databases but carry only a
// target id, so the type label has to come from the main database.
//
// Find rather than Scan: see sampleWebhookQueueDepths.
func (e *Engine) targetTypesByID() (
map[string]database.TargetType, error,
) {
@@ -106,7 +108,7 @@ func (e *Engine) targetTypesByID() (
err := e.database.DB().
Model(&database.Target{}).
Select("id", "type").
Scan(&rows).Error
Find(&rows).Error
if err != nil {
return nil, fmt.Errorf("loading targets: %w", err)
}
@@ -128,6 +130,13 @@ func (e *Engine) targetTypesByID() (
// folds that into the unknown series rather than dropping it: a
// backlog stuck behind a deleted target is a backlog that still needs
// to be alertable.
//
// The aggregate is read with Find, not Scan. (*gorm.DB).Scan swaps
// GORM's own trace recorder in for the logging adapter, and that
// recorder does not implement gorm.ParamsFilter, so the statement
// reaches the log with its bound values interpolated — here, the
// status list. Find goes through the normal query callback, which is
// filtered. See internal/gormlog and its scan_guard_test.go.
func (e *Engine) sampleWebhookQueueDepths(
webhookID string,
types map[string]database.TargetType,
@@ -158,7 +167,7 @@ func (e *Engine) sampleWebhookQueueDepths(
database.DeliveryStatusRetrying,
}).
Group("target_id, status").
Scan(&rows).Error
Find(&rows).Error
if err != nil {
e.log.Error(
"queue depth sample: "+