mirror of https://github.com/panjf2000/ants.git
Support customized logger
This commit is contained in:
parent
ef20703b02
commit
e507ae340f
73
ants.go
73
ants.go
|
@ -24,7 +24,9 @@ package ants
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -81,75 +83,16 @@ var (
|
||||||
return 1
|
return 1
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
defaultLogger = Logger(log.New(os.Stderr, "", log.LstdFlags))
|
||||||
|
|
||||||
// Init a instance pool when importing ants.
|
// Init a instance pool when importing ants.
|
||||||
defaultAntsPool, _ = NewPool(DefaultAntsPoolSize)
|
defaultAntsPool, _ = NewPool(DefaultAntsPoolSize)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Option represents the optional function.
|
// Logger is used for logging formatted messages.
|
||||||
type Option func(opts *Options)
|
type Logger interface {
|
||||||
|
// Printf must have the same semantics as log.Printf.
|
||||||
// Options contains all options which will be applied when instantiating a ants pool.
|
Printf(format string, args ...interface{})
|
||||||
type Options struct {
|
|
||||||
// ExpiryDuration sets the expired time of every worker.
|
|
||||||
ExpiryDuration time.Duration
|
|
||||||
|
|
||||||
// PreAlloc indicates whether to make memory pre-allocation when initializing Pool.
|
|
||||||
PreAlloc bool
|
|
||||||
|
|
||||||
// Max number of goroutine blocking on pool.Submit.
|
|
||||||
// 0 (default value) means no such limit.
|
|
||||||
MaxBlockingTasks int
|
|
||||||
|
|
||||||
// When Nonblocking is true, Pool.Submit will never be blocked.
|
|
||||||
// ErrPoolOverload will be returned when Pool.Submit cannot be done at once.
|
|
||||||
// When Nonblocking is true, MaxBlockingTasks is inoperative.
|
|
||||||
Nonblocking bool
|
|
||||||
|
|
||||||
// PanicHandler is used to handle panics from each worker goroutine.
|
|
||||||
// if nil, panics will be thrown out again from worker goroutines.
|
|
||||||
PanicHandler func(interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithOptions accepts the whole options config.
|
|
||||||
func WithOptions(options Options) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
*opts = options
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithExpiryDuration sets up the interval time of cleaning up goroutines.
|
|
||||||
func WithExpiryDuration(expiryDuration time.Duration) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.ExpiryDuration = expiryDuration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPreAlloc indicates whether it should malloc for workers.
|
|
||||||
func WithPreAlloc(preAlloc bool) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.PreAlloc = preAlloc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithMaxBlockingTasks sets up the maximum number of goroutines that are blocked when it reaches the capacity of pool.
|
|
||||||
func WithMaxBlockingTasks(maxBlockingTasks int) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.MaxBlockingTasks = maxBlockingTasks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithNonblocking indicates that pool will return nil when there is no available workers.
|
|
||||||
func WithNonblocking(nonblocking bool) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.Nonblocking = nonblocking
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPanicHandler sets up panic handler.
|
|
||||||
func WithPanicHandler(panicHandler func(interface{})) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.PanicHandler = panicHandler
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit submits a task to pool.
|
// Submit submits a task to pool.
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
package ants
|
package ants
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -546,7 +548,7 @@ func TestRestCodeCoverage(t *testing.T) {
|
||||||
poolOpts, _ := NewPool(1, WithOptions(options))
|
poolOpts, _ := NewPool(1, WithOptions(options))
|
||||||
t.Logf("Pool with options, capacity: %d", poolOpts.Cap())
|
t.Logf("Pool with options, capacity: %d", poolOpts.Cap())
|
||||||
|
|
||||||
p0, _ := NewPool(TestSize)
|
p0, _ := NewPool(TestSize, WithLogger(log.New(os.Stderr, "", log.LstdFlags)))
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = p0.Submit(demoFunc)
|
_ = p0.Submit(demoFunc)
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package ants
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Option represents the optional function.
|
||||||
|
type Option func(opts *Options)
|
||||||
|
|
||||||
|
func loadOptions(options ...Option) *Options {
|
||||||
|
opts := new(Options)
|
||||||
|
for _, option := range options {
|
||||||
|
option(opts)
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options contains all options which will be applied when instantiating a ants pool.
|
||||||
|
type Options struct {
|
||||||
|
// ExpiryDuration sets the expired time of every worker.
|
||||||
|
ExpiryDuration time.Duration
|
||||||
|
|
||||||
|
// PreAlloc indicates whether to make memory pre-allocation when initializing Pool.
|
||||||
|
PreAlloc bool
|
||||||
|
|
||||||
|
// Max number of goroutine blocking on pool.Submit.
|
||||||
|
// 0 (default value) means no such limit.
|
||||||
|
MaxBlockingTasks int
|
||||||
|
|
||||||
|
// When Nonblocking is true, Pool.Submit will never be blocked.
|
||||||
|
// ErrPoolOverload will be returned when Pool.Submit cannot be done at once.
|
||||||
|
// When Nonblocking is true, MaxBlockingTasks is inoperative.
|
||||||
|
Nonblocking bool
|
||||||
|
|
||||||
|
// PanicHandler is used to handle panics from each worker goroutine.
|
||||||
|
// if nil, panics will be thrown out again from worker goroutines.
|
||||||
|
PanicHandler func(interface{})
|
||||||
|
|
||||||
|
// Logger is the customized logger for logging info, if it is not set, default standard logger from log package is used.
|
||||||
|
Logger Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOptions accepts the whole options config.
|
||||||
|
func WithOptions(options Options) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
*opts = options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithExpiryDuration sets up the interval time of cleaning up goroutines.
|
||||||
|
func WithExpiryDuration(expiryDuration time.Duration) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.ExpiryDuration = expiryDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPreAlloc indicates whether it should malloc for workers.
|
||||||
|
func WithPreAlloc(preAlloc bool) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.PreAlloc = preAlloc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxBlockingTasks sets up the maximum number of goroutines that are blocked when it reaches the capacity of pool.
|
||||||
|
func WithMaxBlockingTasks(maxBlockingTasks int) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.MaxBlockingTasks = maxBlockingTasks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNonblocking indicates that pool will return nil when there is no available workers.
|
||||||
|
func WithNonblocking(nonblocking bool) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Nonblocking = nonblocking
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPanicHandler sets up panic handler.
|
||||||
|
func WithPanicHandler(panicHandler func(interface{})) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.PanicHandler = panicHandler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLogger sets up a customized logger.
|
||||||
|
func WithLogger(logger Logger) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Logger = logger
|
||||||
|
}
|
||||||
|
}
|
9
pool.go
9
pool.go
|
@ -96,10 +96,7 @@ func NewPool(size int, options ...Option) (*Pool, error) {
|
||||||
return nil, ErrInvalidPoolSize
|
return nil, ErrInvalidPoolSize
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := new(Options)
|
opts := loadOptions(options...)
|
||||||
for _, option := range options {
|
|
||||||
option(opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
if expiry := opts.ExpiryDuration; expiry < 0 {
|
if expiry := opts.ExpiryDuration; expiry < 0 {
|
||||||
return nil, ErrInvalidPoolExpiry
|
return nil, ErrInvalidPoolExpiry
|
||||||
|
@ -107,6 +104,10 @@ func NewPool(size int, options ...Option) (*Pool, error) {
|
||||||
opts.ExpiryDuration = DefaultCleanIntervalTime
|
opts.ExpiryDuration = DefaultCleanIntervalTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.Logger == nil {
|
||||||
|
opts.Logger = defaultLogger
|
||||||
|
}
|
||||||
|
|
||||||
p := &Pool{
|
p := &Pool{
|
||||||
capacity: int32(size),
|
capacity: int32(size),
|
||||||
lock: internal.NewSpinLock(),
|
lock: internal.NewSpinLock(),
|
||||||
|
|
|
@ -117,10 +117,7 @@ func NewPoolWithFunc(size int, pf func(interface{}), options ...Option) (*PoolWi
|
||||||
return nil, ErrLackPoolFunc
|
return nil, ErrLackPoolFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := new(Options)
|
opts := loadOptions(options...)
|
||||||
for _, option := range options {
|
|
||||||
option(opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
if expiry := opts.ExpiryDuration; expiry < 0 {
|
if expiry := opts.ExpiryDuration; expiry < 0 {
|
||||||
return nil, ErrInvalidPoolExpiry
|
return nil, ErrInvalidPoolExpiry
|
||||||
|
@ -128,6 +125,10 @@ func NewPoolWithFunc(size int, pf func(interface{}), options ...Option) (*PoolWi
|
||||||
opts.ExpiryDuration = DefaultCleanIntervalTime
|
opts.ExpiryDuration = DefaultCleanIntervalTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.Logger == nil {
|
||||||
|
opts.Logger = defaultLogger
|
||||||
|
}
|
||||||
|
|
||||||
p := &PoolWithFunc{
|
p := &PoolWithFunc{
|
||||||
capacity: int32(size),
|
capacity: int32(size),
|
||||||
poolFunc: pf,
|
poolFunc: pf,
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
package ants
|
package ants
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -54,10 +53,10 @@ func (w *goWorker) run() {
|
||||||
if ph := w.pool.options.PanicHandler; ph != nil {
|
if ph := w.pool.options.PanicHandler; ph != nil {
|
||||||
ph(p)
|
ph(p)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("worker exits from a panic: %v\n", p)
|
w.pool.options.Logger.Printf("worker exits from a panic: %v\n", p)
|
||||||
var buf [4096]byte
|
var buf [4096]byte
|
||||||
n := runtime.Stack(buf[:], false)
|
n := runtime.Stack(buf[:], false)
|
||||||
log.Printf("worker exits from panic: %s\n", string(buf[:n]))
|
w.pool.options.Logger.Printf("worker exits from panic: %s\n", string(buf[:n]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
package ants
|
package ants
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -54,10 +53,10 @@ func (w *goWorkerWithFunc) run() {
|
||||||
if ph := w.pool.options.PanicHandler; ph != nil {
|
if ph := w.pool.options.PanicHandler; ph != nil {
|
||||||
ph(p)
|
ph(p)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("worker with func exits from a panic: %v\n", p)
|
w.pool.options.Logger.Printf("worker with func exits from a panic: %v\n", p)
|
||||||
var buf [4096]byte
|
var buf [4096]byte
|
||||||
n := runtime.Stack(buf[:], false)
|
n := runtime.Stack(buf[:], false)
|
||||||
log.Printf("worker with func exits from panic: %s\n", string(buf[:n]))
|
w.pool.options.Logger.Printf("worker with func exits from panic: %s\n", string(buf[:n]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
Loading…
Reference in New Issue