go-auditGo Audit
Features

Transaction Correlation

Link related data changes and API calls with a shared transaction ID.

A single user action often causes multiple side effects: a DB write, one or more third-party API calls, another DB write. Transaction correlation lets you link them all under one ID so you can replay the full story later.

Generating a Transaction ID

txID := audit.NewTransactionID()
// "20260418T142318-9f3c2a71c8e4d2b15c90a63e4f712b88"

ctx = audit.WithTransactionID(ctx, txID)

NewTransactionID returns a YYYYMMDDTHHmmss-<32-char hex> string — the timestamp prefix makes IDs sortable while the random suffix keeps them globally unique.

Every audit write on that context — data or API — receives the same transaction_id value unless DataEntry.TransactionID or APIEntry.TransactionID is set explicitly on the entry itself.

Full Flow Example

func Transfer(ctx context.Context, orderID string, amount int) error {
    ctx = audit.WithTransactionID(ctx, audit.NewTransactionID())

    // 1. Call the payment gateway — logged to audit_api_logs
    ref, err := bca.Transfer(ctx, amount)
    if err != nil {
        return err
    }

    // 2. Update the order — logged to audit_logs
    return gormDB.WithContext(ctx).
        Model(&Order{}).
        Where("id = ?", orderID).
        Updates(map[string]any{
            "payment_ref": ref,
            "status":      "paid",
        }).Error
}

Both the BCA API call row and the order update row carry the same transaction_id.

Reading the Transaction ID

txID := audit.TransactionIDFromContext(ctx) // "" if unset

Useful inside middleware that wants to log the current transaction ID alongside application logs.

Querying by Transaction

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

Output Shape

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

This gives you a single object that reconstructs the full sequence of side effects for the transaction — perfect for support tickets, post-mortems, and compliance reviews.

Batch Writes

ORM adapters automatically group batch writes under a single transaction_id per SQL statement, even if the caller didn't stamp a transaction ID onto the context. That means every row updated by a bulk UPDATE ... WHERE ... ends up in the same transaction group, and QueryByTransaction returns them together.

On this page