Customizable logger
This commit is contained in:
parent
4465d2c561
commit
797e892120
17
daemon.go
17
daemon.go
|
@ -45,12 +45,13 @@ type Daemon interface {
|
||||||
|
|
||||||
// BaseDaemon is the parent structure for all daemons.
|
// BaseDaemon is the parent structure for all daemons.
|
||||||
type BaseDaemon struct {
|
type BaseDaemon struct {
|
||||||
subscribeFunc SubscribeFunc
|
|
||||||
publisher Publisher
|
|
||||||
self Daemon
|
self Daemon
|
||||||
name string
|
name string
|
||||||
queue chan<- *task
|
queue chan<- *task
|
||||||
|
logger *log.Logger
|
||||||
panicHandler PanicHandler
|
panicHandler PanicHandler
|
||||||
|
subscribeFunc SubscribeFunc
|
||||||
|
publisher Publisher
|
||||||
shutdown chan struct{}
|
shutdown chan struct{}
|
||||||
limit *ratelimit.Bucket
|
limit *ratelimit.Bucket
|
||||||
}
|
}
|
||||||
|
@ -127,10 +128,10 @@ func (d *BaseDaemon) Publish(msg []byte) {
|
||||||
func (d *BaseDaemon) LimitRate(times int, per time.Duration) {
|
func (d *BaseDaemon) LimitRate(times int, per time.Duration) {
|
||||||
rate := float64(time.Second) / float64(per) * float64(times)
|
rate := float64(time.Second) / float64(per) * float64(times)
|
||||||
if rate <= 0 {
|
if rate <= 0 {
|
||||||
log.Println("Daemon %s processing rate was limited to %d. Using 1 instead", d.base(), rate)
|
d.logger.Println("Daemon %s processing rate was limited to %d. Using 1 instead", d.base(), rate)
|
||||||
rate = 1.0
|
rate = 1.0
|
||||||
}
|
}
|
||||||
log.Printf("Daemon %s processing rate is limited to %.2f ops/s", d.base(), rate)
|
d.logger.Printf("Daemon %s processing rate is limited to %.2f ops/s", d.base(), rate)
|
||||||
d.limit = ratelimit.NewBucketWithRate(rate, 1)
|
d.limit = ratelimit.NewBucketWithRate(rate, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +156,14 @@ func (d *BaseDaemon) Continue() bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *BaseDaemon) Log(v ...interface{}) {
|
||||||
|
d.logger.Println(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *BaseDaemon) Logf(format string, v ...interface{}) {
|
||||||
|
d.logger.Printf(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
// String returns the name of the Deamon unerlying struct.
|
// String returns the name of the Deamon unerlying struct.
|
||||||
func (d *BaseDaemon) String() string {
|
func (d *BaseDaemon) String() string {
|
||||||
if d.name == "" {
|
if d.name == "" {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package daemons
|
package daemons
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ type NumberPrinter struct {
|
||||||
// Startup sets up panic handler and starts enqueuing number printing jobs.
|
// Startup sets up panic handler and starts enqueuing number printing jobs.
|
||||||
func (n *NumberPrinter) Startup() {
|
func (n *NumberPrinter) Startup() {
|
||||||
n.HandlePanics(func(err interface{}) {
|
n.HandlePanics(func(err interface{}) {
|
||||||
log.Printf("Oh, crap! There was a panic, take a look: %v", err)
|
n.Logf("Oh, crap! There was a panic, take a look: %v", err)
|
||||||
})
|
})
|
||||||
|
|
||||||
n.LimitRate(3, time.Second)
|
n.LimitRate(3, time.Second)
|
||||||
|
@ -44,6 +43,6 @@ func (n *NumberPrinter) makeActor(num int) satan.Actor {
|
||||||
panic("Nooooo! Random number generator returned a zero!")
|
panic("Nooooo! Random number generator returned a zero!")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Number printer says:", num)
|
n.Log("Number printer says:", num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -15,27 +13,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var debug bool
|
|
||||||
var brokers string
|
var brokers string
|
||||||
|
|
||||||
flag.BoolVar(&debug, "v", false, "Verbose mode")
|
|
||||||
flag.StringVar(&brokers, "brokers", "127.0.0.1:9092", "Kafka broker addresses separated by space")
|
flag.StringVar(&brokers, "brokers", "127.0.0.1:9092", "Kafka broker addresses separated by space")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
log.SetOutput(ioutil.Discard)
|
|
||||||
if debug {
|
|
||||||
log.SetOutput(os.Stderr)
|
|
||||||
}
|
|
||||||
|
|
||||||
kafka.Initialize(strings.Split(brokers, " "))
|
kafka.Initialize(strings.Split(brokers, " "))
|
||||||
defer kafka.Shutdown()
|
defer kafka.Shutdown()
|
||||||
|
|
||||||
logger := stats.NewStdoutLogger(0)
|
statsLogger := stats.NewStdoutLogger(0)
|
||||||
defer logger.Print()
|
defer statsLogger.Print()
|
||||||
|
|
||||||
s := satan.Summon()
|
s := satan.Summon()
|
||||||
s.SubscribeFunc = kafka.Subscribe
|
s.SubscribeFunc = kafka.Subscribe
|
||||||
s.Statistics = logger
|
s.Statistics = statsLogger
|
||||||
|
|
||||||
s.AddDaemon(&daemons.NumberPrinter{})
|
s.AddDaemon(&daemons.NumberPrinter{})
|
||||||
s.AddDaemon(&daemons.PriceConsumer{})
|
s.AddDaemon(&daemons.PriceConsumer{})
|
||||||
|
|
18
satan.go
18
satan.go
|
@ -3,6 +3,7 @@ package satan
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -14,6 +15,7 @@ type Satan struct {
|
||||||
SubscribeFunc SubscribeFunc
|
SubscribeFunc SubscribeFunc
|
||||||
Publisher Publisher
|
Publisher Publisher
|
||||||
Statistics StatsPublisher
|
Statistics StatsPublisher
|
||||||
|
Logger *log.Logger
|
||||||
|
|
||||||
daemons []Daemon
|
daemons []Daemon
|
||||||
queue chan *task
|
queue chan *task
|
||||||
|
@ -83,6 +85,7 @@ var (
|
||||||
// Summon creates a new instance of Satan.
|
// Summon creates a new instance of Satan.
|
||||||
func Summon() *Satan {
|
func Summon() *Satan {
|
||||||
return &Satan{
|
return &Satan{
|
||||||
|
Logger: log.New(os.Stdout, "[daemons] ", log.LstdFlags),
|
||||||
queue: make(chan *task),
|
queue: make(chan *task),
|
||||||
shutdownWorkers: make(chan struct{}),
|
shutdownWorkers: make(chan struct{}),
|
||||||
shutdownSystem: make(chan struct{}),
|
shutdownSystem: make(chan struct{}),
|
||||||
|
@ -96,6 +99,7 @@ func (s *Satan) AddDaemon(d Daemon) {
|
||||||
base.subscribeFunc = s.SubscribeFunc
|
base.subscribeFunc = s.SubscribeFunc
|
||||||
base.publisher = s.Publisher
|
base.publisher = s.Publisher
|
||||||
base.queue = s.queue
|
base.queue = s.queue
|
||||||
|
base.logger = s.Logger
|
||||||
base.shutdown = s.shutdownSystem
|
base.shutdown = s.shutdownSystem
|
||||||
|
|
||||||
go d.Startup()
|
go d.Startup()
|
||||||
|
@ -137,11 +141,11 @@ func (s *Satan) runWorker() {
|
||||||
defer s.wgWorkers.Done()
|
defer s.wgWorkers.Done()
|
||||||
|
|
||||||
i := atomic.AddUint64(&workerIndex, 1)
|
i := atomic.AddUint64(&workerIndex, 1)
|
||||||
log.Printf("Starting worker #%d", i)
|
s.Logger.Printf("Starting worker #%d", i)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Printf("Worker #%d crashed. Error: %v\n", i, err)
|
s.Logger.Printf("Worker #%d crashed. Error: %v\n", i, err)
|
||||||
debug.PrintStack()
|
debug.PrintStack()
|
||||||
go s.runWorker() // Restarting worker
|
go s.runWorker() // Restarting worker
|
||||||
}
|
}
|
||||||
|
@ -155,7 +159,7 @@ func (s *Satan) runWorker() {
|
||||||
s.Statistics.Add("TaskWait", time.Duration(dur))
|
s.Statistics.Add("TaskWait", time.Duration(dur))
|
||||||
s.processTask(t)
|
s.processTask(t)
|
||||||
case <-s.shutdownWorkers:
|
case <-s.shutdownWorkers:
|
||||||
log.Printf("Worker #%d has stopped", i)
|
s.Logger.Printf("Worker #%d has stopped", i)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,17 +181,17 @@ func (s *Satan) processSystemTask(t *task) {
|
||||||
defer s.wgSystem.Done()
|
defer s.wgSystem.Done()
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Printf("System task %s recovered from a panic\nError: %v\n", t, err)
|
s.Logger.Printf("System task %s recovered from a panic\nError: %v\n", t, err)
|
||||||
debug.PrintStack()
|
debug.PrintStack()
|
||||||
|
|
||||||
t.createdAt = time.Now()
|
t.createdAt = time.Now()
|
||||||
s.queue <- t // Restarting task
|
s.queue <- t // Restarting task
|
||||||
} else {
|
} else {
|
||||||
log.Printf("System task %s has stopped\n", t)
|
s.Logger.Printf("System task %s has stopped\n", t)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Printf("Starting system task %s\n", t)
|
s.Logger.Printf("Starting system task %s\n", t)
|
||||||
t.actor() // <--- ACTION STARTS HERE
|
t.actor() // <--- ACTION STARTS HERE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +202,7 @@ func (s *Satan) processGeneralTask(t *task) {
|
||||||
s.Statistics.Error(t.daemon.base().String())
|
s.Statistics.Error(t.daemon.base().String())
|
||||||
}
|
}
|
||||||
t.daemon.base().handlePanic(err)
|
t.daemon.base().handlePanic(err)
|
||||||
log.Printf("Daemon %s recovered from a panic\nError: %v\n", t.daemon.base(), err)
|
s.Logger.Printf("Daemon %s recovered from a panic\nError: %v\n", t.daemon.base(), err)
|
||||||
debug.PrintStack()
|
debug.PrintStack()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
Loading…
Reference in New Issue