Add a statistics pane to the webhook page (closes #368)
check / check (push) Failing after 1m4s
check / check (push) Failing after 1m4s
Each webhook's event database keeps one row of running totals: events, deliveries and failures, and how many of each retention removed. Storing an event, creating a delivery, a delivery becoming failed and the retention sweep each update it in the transaction that writes or deletes the rows it counts. Deliveries get a finished_at column, the last column of the status index, so the last-10-minutes and last-24-hours figures are index-range counts. The pane is its own template, included at the top of the page. The schema changes in place with nothing back-filled, so an existing database must be recreated. Model: opus-5-5
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Totals is the single row of running totals in a webhook's event
|
||||
// database. It is what keeps the webhook page's lifetime figures right
|
||||
// after retention has removed the rows they count, and what lets the
|
||||
// page show them without counting every row.
|
||||
//
|
||||
// Storing an event, creating a delivery and failing a delivery each
|
||||
// add one, and retention adds what it deletes to the Removed columns.
|
||||
// Every addition goes through AddTotals, in the transaction that
|
||||
// writes or deletes the rows it counts.
|
||||
type Totals struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
|
||||
Events int64 `gorm:"not null"`
|
||||
Deliveries int64 `gorm:"not null"`
|
||||
Failures int64 `gorm:"not null"`
|
||||
|
||||
EventsRemoved int64 `gorm:"not null"`
|
||||
DeliveriesRemoved int64 `gorm:"not null"`
|
||||
FailuresRemoved int64 `gorm:"not null"`
|
||||
}
|
||||
|
||||
// TableName names the table AddTotals updates.
|
||||
func (Totals) TableName() string {
|
||||
return "totals"
|
||||
}
|
||||
|
||||
// EventsWithinRetention is how many of the webhook's events are still
|
||||
// stored.
|
||||
func (t Totals) EventsWithinRetention() int64 {
|
||||
return t.Events - t.EventsRemoved
|
||||
}
|
||||
|
||||
// DeliveriesWithinRetention is how many of the webhook's deliveries
|
||||
// are still stored.
|
||||
func (t Totals) DeliveriesWithinRetention() int64 {
|
||||
return t.Deliveries - t.DeliveriesRemoved
|
||||
}
|
||||
|
||||
// FailuresWithinRetention is how many of the webhook's failed
|
||||
// deliveries are still stored.
|
||||
func (t Totals) FailuresWithinRetention() int64 {
|
||||
return t.Failures - t.FailuresRemoved
|
||||
}
|
||||
|
||||
// AddTotals adds each count in add to the webhook's running totals.
|
||||
// Call it on the transaction that writes or deletes the rows it
|
||||
// counts, so the totals change exactly when those rows do.
|
||||
func AddTotals(tx *gorm.DB, add Totals) error {
|
||||
err := tx.Exec(
|
||||
`UPDATE totals SET
|
||||
events = events + ?,
|
||||
deliveries = deliveries + ?,
|
||||
failures = failures + ?,
|
||||
events_removed = events_removed + ?,
|
||||
deliveries_removed = deliveries_removed + ?,
|
||||
failures_removed = failures_removed + ?`,
|
||||
add.Events, add.Deliveries, add.Failures,
|
||||
add.EventsRemoved, add.DeliveriesRemoved, add.FailuresRemoved,
|
||||
).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("adding to running totals: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user