audit is an audit logging library for Go. Audit logging is different
from application logging — application logs record technical details
for debugging (log/slog, zap), while audit logs record who did
what, when, and to which resource for compliance, forensics, and
accountability. If your application handles user data, authentication,
or financial transactions, regulations like SOX, HIPAA, and GDPR
require structured audit trails that application loggers don't enforce.
The library splits audit configuration into two layers:
-
Compile-time (taxonomy): Your event schema — which event types exist, which fields are required, what's optional — is defined in a YAML file and embedded into your binary with
go:embed. A code generator (audit-gen) produces typed Go builders from this schema, so invalid event names and missing required fields are caught by the compiler, not at runtime. The taxonomy is your audit contract — it ships with the binary and cannot be changed without recompiling. -
Runtime (outputs): Where events go — files, syslog, webhooks — is configured in a separate YAML file loaded at startup. Output destinations, routing filters, formatters, and sensitivity label exclusions can all change per environment without rebuilding.
The library validates events against the compiled taxonomy, delivers them asynchronously to multiple outputs simultaneously, and supports both JSON and CEF (Common Event Format) for SIEM integration.
| Feature | Description | Docs |
|---|---|---|
| 📋 Taxonomy Validation | Define event schemas in YAML; every event validated at runtime | Learn more |
| ⚙️ Code Generation | audit-gen generates typed builders; typos become compile errors |
Learn more |
| 🛡️ CEF Format | Common Event Format for SIEM platforms (Splunk, ArcSight, QRadar) | Learn more |
| 📄 JSON Format | Line-delimited JSON with deterministic field order | Learn more |
| 📡 5 Output Types | File (rotation), syslog (RFC 5424), webhook (NDJSON), Loki (stream labels), stdout — fan-out to all simultaneously | Learn more |
| 🔀 Event Routing | Route events by category or severity to specific outputs | Learn more |
| 🔒 Sensitivity Labels | Classify fields as PII/financial; strip per-output for compliance | Learn more |
| ⚡ Async Delivery | Sub-microsecond enqueue; background drain goroutine | Learn more |
| 🌐 HTTP Middleware | Automatically captures HTTP request fields for audit logging | Learn more |
| 📊 Metrics & Monitoring | Track dropped events, delivery errors, and output health | Learn more |
| 📝 YAML Configuration | Configure outputs in YAML with environment variable substitution | Learn more |
| 🔐 HMAC Integrity | Per-output tamper detection with NIST-approved algorithms | Learn more |
| 🧪 Testing Support | In-memory recorder with same validation as production | Learn more |
Audit logging is not application logging. They serve fundamentally different purposes:
| 🔧 Application Logging | 📋 Audit Logging | |
|---|---|---|
| Purpose | Debugging, troubleshooting, observability | Compliance, forensics, accountability |
| Audience | Developers, SREs | Security teams, auditors, legal |
| Guarantees | Best-effort — missing a log line is fine | Schema-enforced — missing a field is a compliance gap |
| Retention | Days to weeks | Months to years (regulatory requirements) |
| Content | Technical details (errors, stack traces) | Who did what, when, to which resource, and why |
| Destinations | Log aggregator (OpenSearch, Datadog, Loki) | SIEM (Splunk, ArcSight, QRadar), compliance archives |
If your application handles user data, financial transactions,
authentication, or access control, regulations like SOX, HIPAA, GDPR,
and PCI-DSS require audit trails. Application loggers (log/slog,
zap, zerolog) do not enforce the structure, completeness, or
delivery guarantees that compliance demands.
No existing Go library provides schema-enforced audit logging with multi-output fan-out and SIEM-native format support:
- 📋 Schema enforcement — every event validated against your taxonomy; missing required fields are rejected, not silently dropped
- 🛡️ SIEM-native output — CEF format understood by Splunk, ArcSight, QRadar out of the box, alongside JSON for log aggregators
- 📡 Multi-output fan-out — send events to files, syslog, webhooks, Loki, and stdout simultaneously, each with its own formatter and filters
- 🔒 Sensitive field stripping — classify fields as PII or financial; strip them per-output for GDPR/PCI compliance
- ⚡ Non-blocking — sub-microsecond
AuditEvent()calls; async delivery via a background drain goroutine with completeness monitoring - 🔌 No vendor lock-in — pluggable metrics interface; no Prometheus, OpenTelemetry, or logging framework dependency in core
The library uses a YAML-first workflow: define your events in a taxonomy file, configure outputs in another, and generate type-safe Go code.
version: 1
categories:
write:
severity: 3
events:
- user_create
security:
severity: 8
events:
- auth_failure
events:
user_create:
description: "A new user account was created"
fields:
outcome: { required: true }
actor_id: { required: true }
auth_failure:
description: "An authentication attempt failed"
fields:
outcome: { required: true }
actor_id: { required: true }💡 Fields like
target_id,source_ip, andreasonare reserved standard fields — always available on every event without declaration. Use.SetTargetID(),.SetSourceIP(), etc. on any builder.
version: 1
app_name: my-service
host: "${HOSTNAME:-localhost}"
outputs:
console:
type: stdout
siem_log:
type: file
file:
path: "./audit-cef.log"
formatter:
type: cef
vendor: "MyCompany"
product: "MyApp"
version: "1.0"go run github.com/axonops/audit/cmd/audit-gen \
-input taxonomy.yaml \
-output audit_generated.go \
-package main💡
go runfetches the tool automatically — no separate install needed.
// Required fields are constructor parameters — typos are compile errors
err := logger.AuditEvent(
NewUserCreateEvent("alice", "success").
SetTargetID("user-42"),
)📚 For the complete runnable application (taxonomy loading, output configuration, logger creation), see examples/02-code-generation.
📄 JSON (default formatter):
{"timestamp":"...","event_type":"user_create","severity":3,"app_name":"my-service","host":"prod-01","timezone":"UTC","pid":12345,"actor_id":"alice","outcome":"success","target_id":"user-42","event_category":"write"}🛡️ CEF (SIEM formatter):
CEF:0|MyCompany|MyApp|1.0|user_create|A new user account was created|3|rt=... act=user_create deviceProcessName=my-service dvchost=prod-01 dvcpid=12345 suser=alice outcome=success cat=write
app_name,host, andpidare framework fields — set once in your outputs.yaml and automatically included in every event. Thehost,timezone, andpidvalues reflect your system — they will differ from the example above.app_nameis set inoutputs.yamland stays constant across deployments. SIEMs use the CEF extension keys (deviceProcessName,dvchost,dvcpid) for automatic host-level correlation.
Requires Go 1.26+.
go get github.com/axonops/audit # core: logger, taxonomy, validation, formatters, stdout output
go get github.com/axonops/audit/file # file output with rotation
go get github.com/axonops/audit/syslog # RFC 5424 syslog (TCP/UDP/TLS/mTLS)
go get github.com/axonops/audit/webhook # batched HTTP webhook with SSRF protection
go get github.com/axonops/audit/loki # Grafana Loki with stream labels and gzip
go get github.com/axonops/audit/outputconfig # YAML-based output configuration💡 The core module includes
StdoutOutput(no additional dependency) and theaudittestpackage for testing.
| Module | Description |
|---|---|
github.com/axonops/audit |
Core: Logger, taxonomy validation, JSON + CEF formatters, HTTP middleware, stdout output, fan-out, routing, audittest |
github.com/axonops/audit/file |
File output with size-based rotation and gzip compression |
github.com/axonops/audit/syslog |
RFC 5424 syslog output (TCP/UDP/TLS/mTLS) |
github.com/axonops/audit/webhook |
Batched HTTP webhook with retry and SSRF protection |
github.com/axonops/audit/loki |
Grafana Loki output with stream labels, gzip, multi-tenancy |
github.com/axonops/audit/outputconfig |
YAML-based output configuration with env var substitution |
github.com/axonops/audit/outputs |
Convenience: single blank import registers all output factories |
github.com/axonops/audit/secrets |
Secret provider interface for ref+ URI resolution in YAML config |
github.com/axonops/audit/secrets/openbao |
OpenBao KV v2 secret provider |
github.com/axonops/audit/secrets/vault |
HashiCorp Vault KV v2 secret provider |
github.com/axonops/audit/cmd/audit-gen |
Code generator: YAML taxonomy to typed Go builders |
Outputs are isolated in separate modules so the core library carries
minimal third-party dependencies. Import only the outputs you use —
or import _ "github.com/axonops/audit/outputs" to register all of them.
The audittest package provides an in-memory recorder for testing audit events:
func TestUserCreation(t *testing.T) {
logger, events, _ := audittest.NewLoggerQuick(t, "user_create")
// Exercise the code under test...
err := logger.AuditEvent(audit.NewEventKV("user_create",
"outcome", "success", "actor_id", "alice"))
require.NoError(t, err)
// Assert immediately — NewLoggerQuick uses synchronous delivery.
assert.Equal(t, 1, events.Count())
assert.Equal(t, "alice", events.Events()[0].StringField("actor_id"))
}See Example 4 and Testing docs for more.
| Resource | Description |
|---|---|
| 📖 Progressive Examples | 17 examples from "hello world" to a complete inventory demo — every output type, TLS policy, routing, formatters, testing, and buffering |
| 📘 API Reference | pkg.go.dev documentation |
| 🏗️ Architecture | Pipeline design, module boundaries, thread safety |
| 🤝 Contributing | Development setup, PR process, code standards |
| 📝 Changelog | Release history and breaking changes |
| ❌ Error Reference | Every error explained with recovery guidance |
| 🔧 Troubleshooting | Common problems and how to fix them |
| 🔒 Security Policy | Vulnerability reporting |
| ⚡ Benchmarks | Performance baseline and methodology |
This library is pre-release (v0.x). The API may change between minor versions until v1.0.0. Pin your dependency version.
audit builds on excellent open-source projects. See ACKNOWLEDGEMENTS.md for full attribution and license details.
- github.com/goccy/go-yaml — YAML parsing (MIT)
- github.com/axonops/srslog — RFC 5424 syslog (BSD-3-Clause)
- github.com/rgooding/go-syncmap — Generic sync.Map (Apache-2.0)
Apache License 2.0 — Copyright 2026 AxonOps Limited.
