go-auditGo Audit
API Reference

Query & Filters

Cross-table queries, retention, snapshot, and restore.

Auditor.QueryByTransaction(ctx, txID) → (*TransactionLog, error)

Fetches all data audit rows and API call rows sharing a transaction_id.

trail, err := auditor.QueryByTransaction(ctx, txID)
// trail.DataLogs  []AuditLog
// trail.APILogs   []AuditAPILog

API logs are only included if APIAudit.Enabled == true.

audit.TransactionLog

Go
type TransactionLog struct {
    TransactionID string
    DataLogs      []AuditLog
    APILogs       []AuditAPILog
}
Go snippet

Use this in UIs that show a transaction timeline or in support tooling that reconstructs what happened during a single user action.

Pagination

Every filter type exposes Limit and Offset:

Go
page1, _ := auditor.Query(ctx, audit.DataFilter{Limit: 25, Offset: 0})
page2, _ := auditor.Query(ctx, audit.DataFilter{Limit: 25, Offset: 25})
Go snippet

For very large tables, prefer keyset pagination against created_at (set the next page's DateTo to the previous page's last row's CreatedAt) over deep offset pagination.

Sorting

All queries return results ordered by id DESC (newest first). Since id is a monotonic auto-increment key, this matches insertion order — effectively created_at DESC for normally-inserted rows.

Transaction ID Helpers

Go
func audit.NewTransactionID() string
func audit.WithTransactionID(ctx context.Context, txID string) context.Context
func audit.TransactionIDFromContext(ctx context.Context) string
Go snippet

NewTransactionID returns a YYYYMMDDTHHmmss-<32-char hex> string (lexicographically sortable by time). TransactionIDFromContext returns the empty string when no ID is set.

Auditor.Purge(ctx, before) → (PurgeResult, error)

Deletes rows older than before from audit_logs and audit_api_logs (only the tables that are enabled).

Go
cutoff := time.Now().AddDate(-1, 0, 0) // 1 year ago
result, err := auditor.Purge(ctx, cutoff)
// result.DataLogs: int64 rows deleted
// result.APILogs:  int64 rows deleted
Go snippet

Returns a PurgeResult:

Go
type PurgeResult struct {
    DataLogs int64
    APILogs  int64
}
Go snippet

Run Purge from a daily cron to enforce retention policies.

Auditor.Snapshot(ctx, entityType, entityID, at) → (map[string]any, error)

Reconstructs the state of an entity at a given point in time by replaying its audit history up to at.

Go
state, err := auditor.Snapshot(ctx,
    "orders", "42",
    time.Date(2026, 3, 1, 12, 0, 0, 0, time.UTC),
)
// state is the map of column → value at that moment
Go snippet

Returns nil (without error) if the entity did not exist or had been deleted at that time. Requires non-empty entityType, entityID, and a non-zero at time.

Useful for "what did this record look like when X happened?" questions during incident response.

Auditor.Restore(ctx, entityType, entityID, at) → (*RestoreResult, error)

Reconstructs the target state via Snapshot, then writes a restore audit entry (old values = current state, new values = target state), and returns the target values for the caller to apply via their ORM.

Go
result, err := auditor.Restore(ctx, "orders", "42", oldTime)
if err != nil { return err }

// Apply the returned values via GORM
gormDB.Model(&Order{ID: 42}).Updates(result.Values)
Go snippet
Go
type RestoreResult struct {
    EntityType string         `json:"entity_type"`
    EntityID   string         `json:"entity_id"`
    Values     map[string]any `json:"values,omitempty"`
    WasDeleted bool           `json:"was_deleted"`
}
Go snippet

The ORM adapter will not record the application-level write as a separate update — the restore audit entry already captures it. Your caller is responsible for actually persisting the restored values.

On this page