I just wrote this a bit over a month ago: https://git.parallelcoin.io/dev/pod/src/branch/master/pkg/util/cl
It was brutal simple before (only one 600 line source lots of type switches) but it now also has a registration system for setting up arbitrary subsystem log levels. By the way, I could be wrong in my thinking about this, but it was central to the design to use interface{} channels and meaningful type names and the variables and inputs for, such as a printf type function, are this way only bundled into a struct literal, no function is called, the execution thread just forks and log messages pass through directly without any function call. I even have a type for closures to pass straight through and they also don't execute until the last step of composing the output, so I have 6 core goroutines and 6 for each subsystem I set up, and most of the work is done in the end of two passes through channels (subsystems drop them if so configured). I think it also has a somewhat crude shutdown handling system in it too. It could definitely do with more work and actual performance overhead in throughput and latency to be profiled and optimised, but being simple I think it's not got much room to improve in the general design. The messages pass through two 'funnels', with one per subsystem gated by its level setting, and then the actual function calls to splice the strings and output the result is deferred until the final 6 channel level main thread. I have just used them mainly on a package level basis but you can declare several in a package they just have to have different string labels. Anyway, I'm kinda proud of it because my specific need is for avoiding such in-thread overheads as possible since during replay of the database log it only runs one thread due to the dependencies between data elements, and I think this does this well but I can't say I have any measurements either way, except I do know that especially permanent allocated channels only have a startup cost and their scheduling is very low cost, and also explicates to the compiler that the processes are concurrent and ideally should not be overlapping each other. The print functions in fmt and log all have the per-call overhead cost, whereas channels have initialisation and lower context switch cost, but yes, more memory use but mainly because it funnels messages from another couple hundred other threads. So that's also my theory and why this post caught my eye. My logger is unlicenced so do whatever you like except pretend it's not prior art. On Saturday, 16 March 2019 17:02:06 UTC+1, Thomas S wrote: > > Hello, > > I have a software needing a lot of logs when processing. > > I need to : > 1- Improve the processing time by doing non-blocking logs > 2- Be safe with goroutines parallel logs > > fmt package doesn't match with (1) & (2) > log package doesn't match with (1) > > *Here is my proposal. What do you think ?* > > *Design :* > > [Log functions] -----channel---->[Buffering function (goroutine)] > ----channel----> [Printing function (goroutine)] > > > package glog > > import ( > "container/list" > "encoding/json" > "fmt" > ) > > /* > ** Public > */ > > func Println(data ...interface{}) { > bufferChan <- fmt.Sprintln(data...) > } > > func Print(data ...interface{}) { > bufferChan <- fmt.Sprint(data...) > } > > func Printf(s string, data ...interface{}) { > go func() { > r := fmt.Sprintf(s, data...) > bufferChan <- r > }() > } > > /* > ** Private > */ > > var bufferChan chan string > var outChan chan string > > func init() { > bufferChan = make(chan string) > outChan = make(chan string) > go centrale() > go buffout() > } > > func centrale() { > var buff *list.List > buff = list.New() > for { > if buff.Len() > 0 { > select { > case outChan <- buff.Front().Value.(string): > buff.Remove(buff.Front()) > case tmp := <-bufferChan: > buff.PushBack(tmp) > } > > } else { > tmp := <-bufferChan > buff.PushBack(tmp) > } > } > } > > func buffout() { > for { > data := <-outChan > fmt.Print(data) > } > } > > > > It works well for now, I want to be sure to not miss anything as it's a > very important part of the code. > > Thank you for your review. > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.