New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[log][survey] Popular logger in Go #26
Comments
Zap
|
benchmark result on my laptop w/o gommon/log
|
Added gommon in at15/zap@a975bfe, but there is no
|
- field does not have good support in gommon, so it is not tested - dyweb/gommon#26
zerolog seems to have its own json encoder .... https://github.com/rs/zerolog/tree/master/internal/json which use direct copy instead of encode when data is not |
after introducing
|
- obtained from https://github.com/avelino/awesome-go#logging - most of them are not very popular, only the few I have already know. - logrus, zap, glog, log15, zerolog, apex/log
- logrus is same as old gommon/log - zap and zerolog for performance - apex-log, for its handler - go-kit and log15, it seems go-kit log is inspired by log15 [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1) - nanolog is very special, might not be used by common library - heap and priority_queue comes in because I was preparing for interview at that time I suppose, around Sep. maybe ...
- gommon/log v1 is modeled after it - `AddField` updates in place and is never actually used - entry represent a log message, its `log` method has non pointer receiver to avoid race condition, because it updates Time, Message etc. - it has hooks, and use mutex to lock the global logger when fire - use buffer pool for bytes.Buffer - use pool for Entry as well
- just a logger struct for everything, use mutex and pointer receiver - it does not have concept of entry like logrus - a slice as buffer (for all the log) - default log to stderr, `std` is the interal default logger where all `log.Printf` goes - support line number, release lock when obtain it via `runtime.Caller`
- user create field (context) by using factory method like `String`, which is a struct contains key, value and type of the value - when log, i.e. calling `Debug("this is msg", zap.String("foo", "bar"))`, `Check` is called, which calls `check` and then calls `Core.Check`, if requirements like level and sample are met, core add itself to the returned `CheckedEntry` - then `CheckedEntry.Write` is called, which loops all the cores and call `Core.Write(entry, fields)` - `Core.Write` calls encoder and write to out (`WriteSyncer`) - when encoding, field has a `AddTo` method which is based on the type stored in the field struct when create, then for int calls `buffer.AddInt`, which calls `strconv.AppendInt`, it is zero allocation compared with `fmt.Sprintf` - for out, there seems to be no lock ... guess just rely on stderr and os.File directly - overall, the implementation is much more complex than stdlib and logrus, it ask user to specify type of the field in order to avoid using reflection (and be type safe), this is mainly for field though - [ ] TODO: actually we can use syntax sugar to wrap those for user automatically, though I don't know how to keep the comment in original code, unless we are using regexp to replace instead of traversing AST
- #26 - checked code for `fmt.Printf`, the real logic is in `printArg(arg interface{}, verb rune)`, which would print simple types like `int`, `[]byte` directly, though there are many indirection and goes to `strconv` eventually. for other types (i.e. type MyInt int), reflection is needed, `printValue(value reflect.Value, verb rune, depth int)` - but `Printf` supports formatting like `%0.2f`, I don't remember how zap would handle that, let user call `fmt.Sprintf` for message maybe?
- focus on a small interface, just `Log(keyvals ...interface{})` - level is not built in, need a wrapper to allow filter by level - the slide talks a lot about std log and log15's design, which is not making good use of interface - it has a adapter for std log, by using regexp to extract info
- it use lock in handler implementations, for logging to stdout/err, I think the reason the lock is needed is they call fmt.Fprintf multiple times (for the message and fields) for a single log entry - the overall process is entry.Debug -> Logger.log -> Handler.HandleLog(*Entry) -> write to ouput (i.e. fmt.Fprintf(io.Writer)) - it's good they didn't put Output inside logger, als othe HandlerFunc part like `net/http`, though I still didn't know why it's using value instead of pointer receiver #30
- it has interesting features like LOG_IF, LOG_EVERY - most stuff are squished into one `glog.go` file - the cpp version has more features, and the code is a little bit hard to read due to using automake to generate header file (h.in)
- detail xml config, filter by level, file, function (require calling runtime, expensive) - many small files, some just have one interface (quite java style ...) - created back in 2011 ...
- add zerolog, it has custom json encoder, didn't look at the code carefully, read it before, more unfriendly than zap - add log4j, lazy evaluation is achieved using Java-8 lambda, similar is done in log15 by passing function and reflect - add nanolog, kind of a like a small database ... reminds me of old days writing xephon-k's storage, calling `binary` package, no context and level support though, like std log w/ smaller disk usage - add complexity part for each library - time to write the design doc for new logv2
- **log4j does not have tree**, it's flat, using string as identifier (a map of loggers), Solr simply split it by dot because class name is used as logger name, the tree is built in front end - all the instances of a class share same logger, because it is `public static final Logger log = LoggerFactory.getLogger(MyClass.class)`
I remembered there is one or two logging in C++ and/or go that log in a compressed format, and requires extra binary to extra this to a human readable format ... it's nano log, also found the golang version
Goals
go test -bench=. -benchmem
Optional Goals
Tracef
when you want a production binary that don't need trace from third party libraryzap.String
stuff for freego/ast
to generate implementation based on interfaceThe text was updated successfully, but these errors were encountered: