Plugin System
Extend Grove with plugins for audit logging, metrics, and custom behavior.
Grove's plugin system lets you extend the ORM with custom behavior at lifecycle boundaries. Plugins are simpler than hooks — they respond to high-level events rather than intercepting individual queries.
Base Interface
Every plugin must implement the Plugin interface:
import "github.com/xraph/grove/plugin"
type Plugin interface {
Name() string
}Lifecycle Hooks
Plugins opt into events by implementing additional interfaces:
Model Events
type AfterRegisterModel interface {
OnModelRegistered(ctx context.Context, table *schema.Table)
}Connection Events
type AfterConnect interface {
OnConnected(ctx context.Context, db *grove.DB)
}
type BeforeClose interface {
OnClosing(ctx context.Context, db *grove.DB) error
}Migration Events
type AfterMigrate interface {
OnMigrated(ctx context.Context, migrations []migrate.AppliedMigration)
}Registering Plugins
// Step 1: Create and connect the driver
pgdb := pgdriver.New()
pgdb.Open(ctx, "postgres://localhost:5432/mydb", driver.WithPoolSize(20))
// Step 2: Open grove.DB with plugins
db, _ := grove.Open(pgdb,
grove.WithPlugin(&MyAuditPlugin{}),
grove.WithPlugin(&MyMetricsPlugin{}),
)Type-Assertion Discovery
The plugin registry uses type assertions to discover which events each plugin handles. Implement only the interfaces you need:
type MyPlugin struct{}
func (p *MyPlugin) Name() string { return "my-plugin" }
// Only implement OnConnected — other events are ignored
func (p *MyPlugin) OnConnected(ctx context.Context, db *grove.DB) {
log.Printf("connected to database")
}Built-in Plugins
Chronicle Audit Plugin
Emits database events to Chronicle for audit trails:
import "github.com/xraph/grove/audit"
auditPlugin := audit.New(chronicleClient)
db, _ := grove.Open(pgdb,
grove.WithPlugin(auditPlugin),
)Events emitted:
grove.query.select/grove.query.insert/grove.query.update/grove.query.deletegrove.migration.applied/grove.migration.rolled_backgrove.connection.opened/grove.connection.closed
Prometheus Metrics Plugin
Exports query performance metrics:
import "github.com/xraph/grove/observability"
metricsPlugin := observability.New()
db, _ := grove.Open(pgdb,
grove.WithPlugin(metricsPlugin),
)Metrics:
grove_queries_total— Total queries by operation and tablegrove_query_duration_seconds— Query latency histogramgrove_connections_active— Active connection countgrove_migrations_total— Migration execution count
KV Store Plugin Compatibility
The KV module (grove/kv) uses the same grove/plugin package for plugin registration. The grove/hook package is shared between the ORM and KV store, so middleware written as hooks works seamlessly across both. See the KV Middleware Overview for KV-specific middleware patterns.