--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
type Field struct {
key string
fieldType fieldType
ival int64
str string
obj interface{}
}
name old time/op new time/op delta
GokitLogfmt-4 3.35µs ± 1% 3.42µs ± 2% +2.11% (p=0.000 n=10+10)
Log15Logfmt-4 17.9µs ± 1% 17.7µs ± 1% -1.19% (p=0.000 n=9+9)
LogrusLogfmt-4 12.8µs ± 1% 13.0µs ± 1% +1.09% (p=0.000 n=10+9)
GokitJSON-4 10.0µs ± 0% 3.5µs ± 0% -64.80% (p=0.000 n=9+10)
Log15JSON-4 18.9µs ± 1% 18.8µs ± 0% -0.39% (p=0.027 n=10+9)
LogrusJSON-4 18.3µs ± 1% 18.4µs ± 0% ~ (p=0.074 n=9+10)
ZapJSON-4 1.57µs ± 1% 1.57µs ± 0% ~ (p=0.741 n=9+9)
name old alloc/op new alloc/op delta
GokitLogfmt-4 320B ± 0% 320B ± 0% ~ (all samples are equal)
Log15Logfmt-4 1.96kB ± 0% 1.96kB ± 0% ~ (all samples are equal)
LogrusLogfmt-4 1.62kB ± 0% 1.62kB ± 0% ~ (all samples are equal)
GokitJSON-4 1.12kB ± 0% 0.32kB ± 0% -71.43% (p=0.000 n=10+10)
Log15JSON-4 1.81kB ± 0% 1.81kB ± 0% ~ (all samples are equal)
LogrusJSON-4 2.30kB ± 0% 2.30kB ± 0% ~ (all samples are equal)
ZapJSON-4 192B ± 0% 192B ± 0% ~ (all samples are equal)
name old allocs/op new allocs/op delta
GokitLogfmt-4 11.0 ± 0% 11.0 ± 0% ~ (all samples are equal)
Log15Logfmt-4 45.0 ± 0% 45.0 ± 0% ~ (all samples are equal)
LogrusLogfmt-4 27.0 ± 0% 27.0 ± 0% ~ (all samples are equal)
GokitJSON-4 32.0 ± 0% 11.0 ± 0% -65.62% (p=0.000 n=10+10)
Log15JSON-4 40.0 ± 0% 40.0 ± 0% ~ (all samples are equal)
LogrusJSON-4 43.0 ± 0% 43.0 ± 0% ~ (all samples are equal)
ZapJSON-4 1.00 ± 0% 1.00 ± 0% ~ (all samples are equal)
For what it's worth, many developers at Uber agree with Peter on the ergonomics/verbosity of specifying types at call sites. A "sugared" logger is in the works (and already being used in our service framework) that provides variadic key/value pairs of eface: https://github.com/uber-go/zap/pull/185/files#diff-1b63c741609271aaf2cacbe869f304c8R68
>>> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "golang-dev" group. >>> To unsubscribe from this group and stop receiving emails from it, send an >>> email to golang-dev+unsubscribe@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. > > -- > You received this message because you are subscribed to the Google Groups "golang-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com. > For more options, visit https://groups.google.com/d/optout.
Rather than argue about whether libraries should log (it’s a losing proposition to argue this),
>>> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "golang-dev" group. >>> To unsubscribe from this group and stop receiving emails from it, send an >>> email to golang-dev+...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. > > -- > You received this message because you are subscribed to the Google Groups "golang-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout.
var log MyFavoriteLogger
log.Error(“whoops!”)
log.Fatal(“aw, man :/”)
type Logger interface {
Info(...interface{}) // or whatever args
Error(...interface{})
Fatal(...interface{})
// … etc
}
type Logger interface{
Log(log.Level, ...interface{}) // or whatever as the args after level
Logf(log.Level, string, ...interface{}) // ? maybe?
// …. WithFields, etc whatever else
}
func (l MyLogger) Log(level log.Level, args ...interface{}) {
switch level {
case log.Warn:
l.Warn(args)
case log.Error:
l.Error(args)
case log.Panic:
l.Error(args) // maybe this library doesn’t believe in log.Panic, so map it to error
// etc ….
default:
l.Print(args) // or whatever
}
}
type Logger interface{
// ...
WithOut(io.Writer) Logger
// ...
}
type F func() func (l LoggerF) Info(f F) { if l.Enabled { f() } }
```
BenchmarkLog/LoggerI:_Disabled-4 2000000 569 ns/op 1008 B/op 9 allocs/op
BenchmarkLog/LoggerF:_Disabled-4 2000000000 0.00 ns/op 0 B/op 0 allocs/op
BenchmarkLog/LoggerI:_Enabled-4 2000000 752 ns/op 1008 B/op 9 allocs/op
BenchmarkLog/LoggerF:_Enabled-4 2000000 748 ns/op 1008 B/op 9 allocs/op
Hello,
By my informal survey, logging in Go applications follows three routes:
- Using some form of fmt.Printf
- Using functions from the log package
- Declaring a log variable at a package level
> [...]
I've tried to codify my solution to this problem with these recommendations.
- libraries should not log error messages, they should return error values
- if libraries need to log _informational_ messages, they should do so
using a value passed in during construction, usually stored in their
structure. I believe this is what Brian refers to when he says "A
common log interface", the type of the logger stored in your type and
availble to methods to use to log informational mesages.
type Log interface {
Print(v ...interface{})
}// common formatted string output
Print(fmt.Sprintf(“some custom print string: %s”, value))
// no format string, just values
Print(someText, struct1, struct2, err)
// Custom key value style structs that can be interrogated with the logger that satisfied the interface to create structured loggin
Print(keyValueStruct, keyValueStruct, keyValueStruct)
// log levels (with a clog style implementation)
Print(“info: starting up system”)
Print(fmt.Sprintf(“err: kaboom %s”, err))I couldn't agree more.
Brian Ketelsen made a Tweet recently
https://twitter.com/bketelsen/status/820768241849077760
which spawned an interesting proto-discussion about logging, tracing,
error reporting, and metrics, with Sameer, Rakyll, Dave, and other
titans of industry. We quickly outgrew the limits of Twitter, so I've
started this thread to continue the conversation.
Here are the questions as I see them:
1) What would a "standardized" logging interface look like?
2) How would that interface interact with related concerns e.g.
context, tracing, instrumentation?
--
> The benefit of a standard interface is that a program wide selection can be configured once like for example db/sql does.
I think when you read "interface" as in Application Programming Interface.
What I'm talking about is "interfaces" as in type logger interface.