Ent Adapter
Use Go Audit with the Ent ORM via a mutation hook.
The Ent adapter attaches a mutation hook so every create, update, and delete is captured.
Installation
go get github.com/gopackx/go-audit/adapters/entSetup
import (
"context"
"database/sql"
"github.com/gopackx/go-audit"
auditent "github.com/gopackx/go-audit/adapters/ent"
"entgo.io/ent/dialect"
entsql "entgo.io/ent/dialect/sql"
"your.app/ent" // generated
)
driver := entsql.OpenDB(dialect.Postgres, sqlDB)
client := ent.NewClient(ent.Driver(driver))
auditor, err := audit.New(sqlDB, audit.Config{
Dialect: audit.PostgreSQL,
UserFunc: func(ctx context.Context) (string, string) {
return "user-123", "user"
},
DataAudit: audit.DataAuditConfig{Enabled: true},
})
if err != nil {
return err
}
client.Use(auditent.Hook(auditor))
if err := auditor.AutoMigrate(context.Background()); err != nil {
return err
}How It Works
auditent.Hook(auditor) returns an ent.Hook that wraps every
mutation:
- For single-row UPDATEs and DELETEs, reads the pre-mutation field
values via
mutation.OldField(...). - Lets the mutation run.
- Records the audit entry with the appropriate action, using the
mutation's
ID()orIDs(ctx)to identify affected rows.
Supported Operations
Create,CreateBulkUpdate,UpdateOneDelete,DeleteOne
For bulk Update / Delete operations, Ent exposes the affected IDs
via mutation.IDs(ctx) but not the pre-mutation field values.
The adapter emits one audit row per affected ID without old_values.
Error Handling
Because the hook wraps the mutation, ErrorFailLoud works like GORM's
AddError: a failed audit write is returned from Mutate as
go-audit: record <action>: <store error> (unwrap with errors.Is /
errors.As) together with the mutation result. The mutation itself
has already been applied when the audit store fails, so fail-loud
reports the failure; it does not roll the write back on its own.
Returning that error from a transaction closure rolls the write back.
For bulk mutations (CreateBulk, bulk Update / Delete) every
affected row is still offered to the store; the failures are joined
into one error (errors.Join) and returned once all rows have been
attempted.
Under ErrorFailSilent the auditor logs the failure via
Config.Logger and Mutate returns nil as usual.
Caveats
- Bulk old values are unavailable. This is an Ent design limitation — the framework does not surface pre-mutation state for many-row operations.
- Hook order matters. Register the audit hook last so it sees the final mutation state after any application-level hooks have run.
- Raw SQL via
client.ExecContext()/driver.ExecContext()is not tracked.