Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions audit/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ func (e *AuditEvent) WithDataFromString(data string) *AuditEvent {
return e.WithData(&rawMsg)
}

// LevelAudit is a custom slog level for audit events, sitting between
// [slog.LevelInfo] (0) and [slog.LevelWarn] (4). Logging audit events at this
// dedicated level lets log infrastructure filter them independently from
// regular application logs. Pass it as the level argument to [AuditEvent.LogTo]
// and as the Level in a handler's [slog.HandlerOptions] so all ToolHive
// components share one definition rather than hardcoding the numeric value.
const LevelAudit = slog.Level(2)

// LogTo logs the audit event to the provided slog.Logger using the custom audit level.
func (e *AuditEvent) LogTo(ctx context.Context, logger *slog.Logger, level slog.Level) {
// Create slog attributes for the audit event
Expand Down
13 changes: 11 additions & 2 deletions audit/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ func TestConstants(t *testing.T) {
t.Parallel()
assert.Equal(t, "toolhive-api", ComponentToolHive)
})

t.Run("audit level", func(t *testing.T) {
t.Parallel()
// Value must stay between Info and Warn so audit events can be
// filtered independently. Changing it is a breaking change for
// consumers that hardcode the numeric level.
assert.Equal(t, slog.Level(2), LevelAudit)
assert.Greater(t, LevelAudit, slog.LevelInfo)
assert.Less(t, LevelAudit, slog.LevelWarn)
})
}

func TestEventMetadataExtra(t *testing.T) {
Expand Down Expand Up @@ -249,8 +259,7 @@ func TestAuditEventLogTo(t *testing.T) {
"transport": "sse",
}

customLevel := slog.Level(2)
event.LogTo(context.Background(), logger, customLevel)
event.LogTo(context.Background(), logger, LevelAudit)

logOutput := buf.String()
require.NotEmpty(t, logOutput)
Expand Down
Loading