Documentation
¶
Overview ¶
Package audithook is a Dispatch extension that bridges lifecycle events to an immutable audit trail backend such as Chronicle.
Every job, workflow, and cron lifecycle hook emits a structured audit event through the Recorder interface. The extension assigns appropriate severity levels (info for normal operations, warning for retries, critical for terminal failures) and rich metadata (job name, queue, elapsed time, errors).
Operator actions taken through the engine (cancel, retry, DLQ replay, delete and purge, cron enable, disable, delete and trigger, workflow replay) are recorded under CategoryOperator, with actions such as ActionOperatorJobCancelled. The acting subject is in Metadata["actor"].
Usage with Chronicle ¶
audithook.New(audithook.RecorderFunc(func(ctx context.Context, evt *audithook.AuditEvent) error {
return chronicle.Info(ctx, evt.Action, evt.Resource, evt.ResourceID).
Category(evt.Category).
Outcome(evt.Outcome).
Record()
}))
Selective filtering ¶
audithook.New(recorder,
audithook.WithActions(
audithook.ActionJobFailed,
audithook.ActionJobDLQ,
audithook.ActionWorkflowFailed,
),
)
Index ¶
- Constants
- func AllActions() []string
- type AuditEvent
- type Extension
- func (e *Extension) Name() string
- func (e *Extension) OnCronFired(ctx context.Context, entryName string, jobID id.JobID) error
- func (e *Extension) OnJobCancelled(ctx context.Context, j *job.Job) error
- func (e *Extension) OnJobCompleted(ctx context.Context, j *job.Job, elapsed time.Duration) error
- func (e *Extension) OnJobDLQ(ctx context.Context, j *job.Job, jobErr error) error
- func (e *Extension) OnJobEnqueued(ctx context.Context, j *job.Job) error
- func (e *Extension) OnJobFailed(ctx context.Context, j *job.Job, jobErr error) error
- func (e *Extension) OnJobRetrying(ctx context.Context, j *job.Job, attempt int, nextRunAt time.Time) error
- func (e *Extension) OnJobStarted(ctx context.Context, j *job.Job) error
- func (e *Extension) OnOperatorAction(ctx context.Context, a ext.Action) error
- func (e *Extension) OnWorkflowCompleted(ctx context.Context, r *workflow.Run, elapsed time.Duration) error
- func (e *Extension) OnWorkflowFailed(ctx context.Context, r *workflow.Run, runErr error) error
- func (e *Extension) OnWorkflowStarted(ctx context.Context, r *workflow.Run) error
- func (e *Extension) OnWorkflowStepCompleted(ctx context.Context, r *workflow.Run, stepName string, elapsed time.Duration) error
- func (e *Extension) OnWorkflowStepFailed(ctx context.Context, r *workflow.Run, stepName string, stepErr error) error
- type Option
- type Recorder
- type RecorderFunc
Constants ¶
const ( ActionJobEnqueued = "job.enqueued" ActionJobStarted = "job.started" ActionJobCompleted = "job.completed" ActionJobFailed = "job.failed" ActionJobRetrying = "job.retrying" ActionJobDLQ = "job.dlq" ActionJobCancelled = "job.cancelled" ActionWorkflowStarted = "workflow.started" ActionWorkflowStepCompleted = "workflow.step_completed" ActionWorkflowStepFailed = "workflow.step_failed" ActionWorkflowCompleted = "workflow.completed" ActionWorkflowFailed = "workflow.failed" ActionCronFired = "cron.fired" )
Audit event actions. Each constant corresponds to one ext lifecycle hook and becomes the Action field of the audit event.
const ( ActionOperatorJobCancelled = "operator.job_cancelled" ActionOperatorJobRetried = "operator.job_retried" ActionOperatorDLQReplayed = "operator.dlq_replayed" ActionOperatorDLQDeleted = "operator.dlq_deleted" ActionOperatorDLQPurged = "operator.dlq_purged" ActionOperatorCronEnabled = "operator.cron_enabled" ActionOperatorCronDisabled = "operator.cron_disabled" ActionOperatorCronDeleted = "operator.cron_deleted" ActionOperatorCronTriggered = "operator.cron_triggered" ActionOperatorWorkflowReplayed = "operator.workflow_replayed" )
Operator audit actions. Each constant corresponds to one ext.ActionKind and is recorded under CategoryOperator, so an operator's cancel stays distinct from the job.cancelled lifecycle event it causes.
const ( CategoryJob = "dispatch.job" CategoryWorkflow = "dispatch.workflow" CategoryCron = "dispatch.cron" CategoryOperator = "dispatch.operator" )
Audit event categories group related actions.
const ( ResourceJob = "job" ResourceWorkflow = "workflow_run" ResourceCron = "cron_entry" ResourceDLQ = "dlq_entry" )
Resource types used as the Resource field in audit events.
const ( SeverityInfo = "info" SeverityWarning = "warning" SeverityCritical = "critical" )
Severity constants (mirror chronicle/audit).
const ( OutcomeSuccess = "success" OutcomeFailure = "failure" )
Outcome constants (mirror chronicle/audit).
Variables ¶
This section is empty.
Functions ¶
func AllActions ¶
func AllActions() []string
AllActions returns every action this extension can emit.
Types ¶
type AuditEvent ¶
type AuditEvent struct {
// What happened
Action string `json:"action"`
Resource string `json:"resource"`
Category string `json:"category"`
// Details
ResourceID string `json:"resource_id,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
Outcome string `json:"outcome"`
Severity string `json:"severity"`
Reason string `json:"reason,omitempty"`
}
AuditEvent is a local representation of an audit event. It mirrors chronicle/audit.Event but avoids a module dependency. Callers provide a RecorderFunc adapter that bridges to their audit backend.
type Extension ¶
type Extension struct {
// contains filtered or unexported fields
}
Extension bridges Dispatch lifecycle events to an audit trail backend. Each lifecycle hook emits a structured audit event through the Recorder.
func (*Extension) OnCronFired ¶
OnCronFired implements ext.CronFired.
func (*Extension) OnJobCancelled ¶
OnJobCancelled implements ext.JobCancelled.
func (*Extension) OnJobCompleted ¶
OnJobCompleted implements ext.JobCompleted.
func (*Extension) OnJobEnqueued ¶
OnJobEnqueued implements ext.JobEnqueued.
func (*Extension) OnJobFailed ¶
OnJobFailed implements ext.JobFailed.
func (*Extension) OnJobRetrying ¶
func (e *Extension) OnJobRetrying(ctx context.Context, j *job.Job, attempt int, nextRunAt time.Time) error
OnJobRetrying implements ext.JobRetrying.
func (*Extension) OnJobStarted ¶
OnJobStarted implements ext.JobStarted.
func (*Extension) OnOperatorAction ¶
OnOperatorAction implements ext.OperatorActionObserver. AuditEvent has no field for the acting subject, so it goes into Metadata["actor"]. IDs that do not apply to the kind are left out of Metadata. A kind this version does not know is still recorded, as "operator." plus the kind with its dots turned into underscores.
func (*Extension) OnWorkflowCompleted ¶
func (e *Extension) OnWorkflowCompleted(ctx context.Context, r *workflow.Run, elapsed time.Duration) error
OnWorkflowCompleted implements ext.WorkflowCompleted.
func (*Extension) OnWorkflowFailed ¶
OnWorkflowFailed implements ext.WorkflowFailed.
func (*Extension) OnWorkflowStarted ¶
OnWorkflowStarted implements ext.WorkflowStarted.
type Option ¶
type Option func(*Extension)
Option configures an Extension.
func WithActions ¶
WithActions restricts the extension to emit only the listed actions. By default every action in AllActions is enabled. Unknown actions are silently ignored.
Example:
audithook.New(emitter,
audithook.WithActions(
audithook.ActionJobCompleted,
audithook.ActionJobFailed,
audithook.ActionJobDLQ,
),
)
func WithLogger ¶
WithLogger sets a custom logger for the extension.
type Recorder ¶
type Recorder interface {
// Record persists a fully-formed audit event.
Record(ctx context.Context, event *AuditEvent) error
}
Recorder is the interface that audit backends must implement. This matches chronicle.Emitter but is defined locally so that the audit_hook package does not import Chronicle directly — callers inject the concrete *chronicle.Chronicle at wiring time.
type RecorderFunc ¶
type RecorderFunc func(ctx context.Context, event *AuditEvent) error
RecorderFunc is an adapter to use a plain function as a Recorder.
Example bridging to Chronicle:
audithook.RecorderFunc(func(ctx context.Context, evt *audithook.AuditEvent) error {
b := chronicle.Info(ctx, evt.Action, evt.Resource, evt.ResourceID).
Category(evt.Category).
Outcome(evt.Outcome)
for k, v := range evt.Metadata {
b = b.Meta(k, v)
}
return b.Record()
})
func (RecorderFunc) Record ¶
func (f RecorderFunc) Record(ctx context.Context, event *AuditEvent) error