Add granunal logging config controls.

This commit is contained in:
Jay
2026-04-23 18:48:47 -04:00
parent 727dc18b57
commit 2a6cd3a487
10 changed files with 248 additions and 101 deletions
+118 -82
View File
@@ -8,88 +8,6 @@ import (
"time"
)
// Worker Config
type WorkerConfig struct {
MaxQueueSize int
InactivityTimeout time.Duration
}
type WorkerOption func(*WorkerConfig) error
func NewWorkerConfig(options ...WorkerOption) (*WorkerConfig, error) {
conf := GetDefaultWorkerConfig()
if err := applyWorkerOptions(conf, options...); err != nil {
return nil, err
}
if err := ValidateWorkerConfig(conf); err != nil {
return nil, err
}
return conf, nil
}
func GetDefaultWorkerConfig() *WorkerConfig {
return &WorkerConfig{
MaxQueueSize: 0, // queue can grow indefinitely by default
InactivityTimeout: 0, // eviction disabled by default
}
}
func applyWorkerOptions(config *WorkerConfig, options ...WorkerOption) error {
for _, option := range options {
if err := option(config); err != nil {
return err
}
}
return nil
}
func ValidateWorkerConfig(config *WorkerConfig) error {
if err := validateMaxQueueSize(config.MaxQueueSize); err != nil {
return err
}
if err := validateInactivityTimeout(config.InactivityTimeout); err != nil {
return err
}
return nil
}
func validateMaxQueueSize(value int) error {
if value < 0 {
return InvalidMaxQueueSize
}
return nil
}
func validateInactivityTimeout(value time.Duration) error {
if value < 0 {
return InvalidInactivityTimeout
}
return nil
}
// When MaxQueueSize is zero, queue limits are disabled.
func WithMaxQueueSize(value int) WorkerOption {
return func(c *WorkerConfig) error {
if err := validateMaxQueueSize(value); err != nil {
return err
}
c.MaxQueueSize = value
return nil
}
}
// When InactivityTimeout is zero, the watchdog is disabled.
func WithInactivityTimeout(value time.Duration) WorkerOption {
return func(c *WorkerConfig) error {
if err := validateInactivityTimeout(value); err != nil {
return err
}
c.InactivityTimeout = value
return nil
}
}
// Pool Config
type WorkerFactory func(
@@ -104,6 +22,8 @@ type PoolConfig struct {
InboxBufferSize int
EventsBufferSize int
ErrorsBufferSize int
LoggingEnabled bool
LogLevel *slog.Level
ConnectionConfig *transport.ConnectionConfig
WorkerConfig *WorkerConfig
WorkerFactory WorkerFactory
@@ -127,6 +47,8 @@ func GetDefaultPoolConfig() *PoolConfig {
InboxBufferSize: 256,
EventsBufferSize: 10,
ErrorsBufferSize: 10,
LoggingEnabled: true,
LogLevel: nil,
ConnectionConfig: nil,
WorkerConfig: nil,
WorkerFactory: nil,
@@ -193,6 +115,20 @@ func WithErrorsBufferSize(value int) PoolOption {
}
}
func WithPoolLoggingEnabled(value bool) PoolOption {
return func(c *PoolConfig) error {
c.LoggingEnabled = value
return nil
}
}
func WithPoolLogLevel(level slog.Level) PoolOption {
return func(c *PoolConfig) error {
c.LogLevel = &level
return nil
}
}
func WithConnectionConfig(cc *transport.ConnectionConfig) PoolOption {
return func(c *PoolConfig) error {
if err := transport.ValidateConnectionConfig(cc); err != nil {
@@ -219,3 +155,103 @@ func WithWorkerFactory(wf WorkerFactory) PoolOption {
return nil
}
}
// Worker Config
type WorkerConfig struct {
MaxQueueSize int
InactivityTimeout time.Duration
LoggingEnabled bool
LogLevel *slog.Level
}
type WorkerOption func(*WorkerConfig) error
func NewWorkerConfig(options ...WorkerOption) (*WorkerConfig, error) {
conf := GetDefaultWorkerConfig()
if err := applyWorkerOptions(conf, options...); err != nil {
return nil, err
}
if err := ValidateWorkerConfig(conf); err != nil {
return nil, err
}
return conf, nil
}
func GetDefaultWorkerConfig() *WorkerConfig {
return &WorkerConfig{
MaxQueueSize: 0, // queue can grow indefinitely by default
InactivityTimeout: 0, // eviction disabled by default
LoggingEnabled: true,
LogLevel: nil,
}
}
func applyWorkerOptions(config *WorkerConfig, options ...WorkerOption) error {
for _, option := range options {
if err := option(config); err != nil {
return err
}
}
return nil
}
func ValidateWorkerConfig(config *WorkerConfig) error {
if err := validateMaxQueueSize(config.MaxQueueSize); err != nil {
return err
}
if err := validateInactivityTimeout(config.InactivityTimeout); err != nil {
return err
}
return nil
}
func validateMaxQueueSize(value int) error {
if value < 0 {
return InvalidMaxQueueSize
}
return nil
}
func validateInactivityTimeout(value time.Duration) error {
if value < 0 {
return InvalidInactivityTimeout
}
return nil
}
// When MaxQueueSize is zero, queue limits are disabled.
func WithMaxQueueSize(value int) WorkerOption {
return func(c *WorkerConfig) error {
if err := validateMaxQueueSize(value); err != nil {
return err
}
c.MaxQueueSize = value
return nil
}
}
// When InactivityTimeout is zero, the watchdog is disabled.
func WithInactivityTimeout(value time.Duration) WorkerOption {
return func(c *WorkerConfig) error {
if err := validateInactivityTimeout(value); err != nil {
return err
}
c.InactivityTimeout = value
return nil
}
}
func WithWorkerLoggingEnabled(value bool) WorkerOption {
return func(c *WorkerConfig) error {
c.LoggingEnabled = value
return nil
}
}
func WithWorkerLogLevel(level slog.Level) WorkerOption {
return func(c *WorkerConfig) error {
c.LogLevel = &level
return nil
}
}
+4
View File
@@ -19,6 +19,8 @@ func TestDefaultWorkerConfig(t *testing.T) {
assert.Equal(t, &WorkerConfig{
MaxQueueSize: 0,
InactivityTimeout: 0,
LoggingEnabled: true,
LogLevel: nil,
}, conf)
}
@@ -104,6 +106,8 @@ func TestDefaultPoolConfig(t *testing.T) {
InboxBufferSize: 256,
EventsBufferSize: 10,
ErrorsBufferSize: 10,
LoggingEnabled: true,
LogLevel: nil,
ConnectionConfig: nil,
WorkerConfig: nil,
WorkerFactory: nil,
+10 -8
View File
@@ -90,7 +90,6 @@ func NewPool(ctx context.Context, id string, config *PoolConfig, handler slog.Ha
// The factory function should be non-blocking or else Connect() may cause
// deadlocks.
if config.WorkerFactory == nil {
// TODO: Construct worker logger
config.WorkerFactory = func(
ctx context.Context,
id string,
@@ -109,8 +108,9 @@ func NewPool(ctx context.Context, id string, config *PoolConfig, handler slog.Ha
pctx, cancel := context.WithCancel(ctx)
var logger *slog.Logger
if handler != nil {
logger = logging.NewInboundPoolLogger(handler, id)
if handler != nil && config.LoggingEnabled {
logger = logging.NewInboundPoolLogger(
logging.WrapOrDefault(config.LogLevel, handler), id)
}
return &Pool{
@@ -249,8 +249,9 @@ func (p *Pool) Send(id string, data []byte) error {
// addLocked constructs and registers a peer. Caller must hold p.mu write lock.
func (p *Pool) addLocked(id string, socket types.Socket) error {
var logger *slog.Logger
if p.handler != nil {
logger = logging.NewConnectionLogger(p.handler, p.id, id)
if p.handler != nil && p.config.ConnectionConfig.LoggingEnabled {
logger = logging.NewConnectionLogger(
logging.WrapOrDefault(p.config.ConnectionConfig.LogLevel, p.handler), p.id, id)
}
conn, err := transport.NewConnectionFromSocket(
@@ -259,12 +260,13 @@ func (p *Pool) addLocked(id string, socket types.Socket) error {
return err
}
// The worker factory must be non-blocking to avoid deadlocks
wctx, cancel := context.WithCancel(p.ctx)
if p.handler != nil {
logger = logging.NewInboundWorkerLogger(p.handler, p.id, id)
if p.handler != nil && p.config.WorkerConfig.LoggingEnabled {
logger = logging.NewInboundWorkerLogger(
logging.WrapOrDefault(p.config.WorkerConfig.LogLevel, p.handler), p.id, id)
}
// The worker factory must be non-blocking to avoid deadlocks
worker, err := p.config.WorkerFactory(wctx, id, conn, p.config.WorkerConfig, logger)
if err != nil {
cancel()