go-auditGo Audit
Guides

Migrating from Manual Audit

Move from hand-written audit code to Go Audit's ORM hooks.

Many Go projects end up with hand-rolled audit code — a helper like recordAudit(...) called after every write. It works, but:

  • Easy to forget on new code paths.
  • Scattered logic, hard to audit itself.
  • Manual diff computation is error-prone.

Go Audit replaces all of that with ORM-level hooks and a single entry point for code paths that bypass the ORM.

Step 1 — Install and Register

go get github.com/gopackx/go-audit
go get github.com/gopackx/go-audit/adapters/gorm
sqlDB, _ := gormDB.DB()

auditor, _ := audit.New(sqlDB, audit.Config{
    Dialect:   audit.PostgreSQL,
    UserFunc:  yourExistingUserExtractor,
    DataAudit: audit.DataAuditConfig{Enabled: true},
})
_ = gormDB.Use(auditgorm.Plugin(auditor))
_ = auditor.AutoMigrate(ctx)

Step 2 — Map Existing Config

If you had a config like this:

var auditConfig = struct {
    ExcludedFields   []string
    ExcludedEntities []string
}{
    ExcludedFields:   []string{"password", "token"},
    ExcludedEntities: []string{"sessions"},
}

Port it straight into DataAuditConfig:

DataAudit: audit.DataAuditConfig{
    Enabled:         true,
    ExcludeFields:   auditConfig.ExcludedFields,
    ExcludeEntities: auditConfig.ExcludedEntities,
}

Step 3 — Remove Manual Calls

Delete your recordAudit(...) calls from code paths that go through the ORM. The plugin now captures them automatically.

For code paths that don't go through the ORM (raw SQL, external imports, background workers writing via database/sql), switch to auditor.RecordDataChange:

_ = auditor.RecordDataChange(ctx, audit.DataEntry{
    EntityType: "ledger_entries",
    EntityID:   fmt.Sprint(entry.ID),
    Action:     audit.ActionCreate,
    NewValues:  map[string]any{"amount": entry.Amount, "account": entry.Account},
})

Step 4 — Migrate the Table

If your existing audit table shape doesn't match Go Audit's, the easiest path is side-by-side:

  1. Run auditor.AutoMigrate(ctx) — creates a fresh audit_logs table (defaults to the name audit_logs; override via DataAudit.Table if you need to coexist).
  2. Write a one-off migration that copies legacy rows into the new shape (or leave them in place as read-only historical data).
  3. Update your read UI to query the new table.

Verifying the Cut-Over

Run both systems side-by-side for a day:

  • Keep the old recordAudit(...) calls.
  • Enable Go Audit's plugin.
  • Spot-check that rows agree on entity, action, and diff shape.
  • Remove the old calls once you're confident.

Payoff

  • Every code path is audited automatically, including future ones.
  • Diff computation is handled, including the "nothing changed" case.
  • Transaction correlation gives you cross-system traces for free.
  • Snapshot / Restore / Purge come along for free.

On this page