-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Refactor logp and add structured logging support #5901
Refactor logp and add structured logging support #5901
Conversation
627ed2b
to
de9c662
Compare
This refactors logp and adds support for structured logging. logp uses github.com/uber-go/zap in its implementation. There are no changes to the user facing logging configuration. The logger output will have some format differences, but in general will have a more consistent format across outputs. Here is some sample output taken from the `TestLogger` test case. ``` === RUN TestLogger 2017-12-17T19:48:16.374-0500 INFO logp/core_test.go:13 unnamed global logger 2017-12-17T19:48:16.374-0500 INFO [example] logp/core_test.go:16 some message 2017-12-17T19:48:16.374-0500 INFO [example] logp/core_test.go:17 some message with parameter x=1, y=2 2017-12-17T19:48:16.374-0500 INFO [example] logp/core_test.go:18 some message {"x": 1, "y": 2} 2017-12-17T19:48:16.374-0500 INFO [example] logp/core_test.go:19 some message {"x": 1} 2017-12-17T19:48:16.374-0500 INFO [example] logp/core_test.go:20 some message with namespaced args {"metrics": {"x": 1, "y": 1}} 2017-12-17T19:48:16.374-0500 INFO [example] logp/core_test.go:21 {"empty_message": true} 2017-12-17T19:48:16.374-0500 WARN [example] logp/core_test.go:24 logger with context {"x": 1, "y": 2} 2017-12-17T19:48:16.374-0500 INFO [example] logp/core_test.go:30 some message with struct value {"metrics": {"x":1,"y":2}} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","caller":"logp/core_test.go:13","message":"unnamed global logger"} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:16","message":"some message"} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:17","message":"some message with parameter x=1, y=2"} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:18","message":"some message","x":1,"y":2} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:19","message":"some message","x":1} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:20","message":"some message with namespaced args","metrics":{"x":1,"y":1}} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:21","message":"","empty_message":true} {"level":"warn","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:24","message":"logger with context","x":1,"y":2} {"level":"info","timestamp":"2017-12-17T19:48:16.374-0500","logger":"example","caller":"logp/core_test.go:30","message":"some message with struct value","metrics":{"x":1,"y":2}} ``` Any test code that calls `logp.LogInit()` in libbeat needs to be updated to use `logp.TestingSetup()`.
de9c662
to
4e62c0e
Compare
if testing.Verbose() { | ||
logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"fileset", "modules"}) | ||
} | ||
logp.TestingSetup(logp.WithSelectors("fileset", "modules")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
// The Logger should be used to use with libraries havng a configurable logging | ||
// functionality. | ||
// LogOption configures a Logger. | ||
type LogOption = zap.Option |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this only works in Go 1.9, right? I think that's fine, just flagging in case this blocks some use case (like gccgo).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, type aliasing is only 1.9.
Should be OK in GCC8, not sure when is the release date.
Due to the alignment of Go's semiannual release schedule with GCC's annual release schedule, GCC release 7 contains the Go 1.8.3 version of gccgo. We expect that the next release, GCC 8, will contain the Go 1.10 version of gccgo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++, I think we're good to make use of it, as go 1.10 is in beta now so I imagine it's not that long until there's a GCC version that can work with it.
@elastic/apm This will also affect logging of the apm-server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change LGTM. I'm fine to introduce this breaking change also in a minor release but we must be aware that it could break in some cases for users. For example if someone uses filebeat to fetch logs for metricbeat and has a filter for ERR
things would not work anymore.
The part I'm more worried about is changing the default "log output". Does this change in this PR? I think we should definitively change it for 7.0 but not sure if we can introduce it in a minor.
For 7.0 we should also do a follow up cleanup like removing Critical
completely, change to JSON logging as default. We should have a follow up discussion / issue about this.
@@ -15,20 +15,19 @@ | |||
|
|||
The `logging` section of the +{beatname_lc}.yml+ config file contains options | |||
for configuring the Beats logging output. The logging system can write logs to | |||
the syslog or rotate log files. If logging is not explicitly configured, file | |||
output is used on Windows systems, and syslog output is used on Linux and OS X. | |||
the syslog or rotate log files. If logging is not explicitly configured the file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a breaking change. Should we only make this for 7.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It didn't make this change. I just fixed the docs to match the behavior 😄 . This was changed in 5.0 I believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ups :-) We should probably backport this part of the doc changes to 6.1/6.0 then. @dedemorton FYI
|
||
Each log message consists of the following parts: | ||
|
||
* Timestamp in ISO8601 format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did the timestamp format change or are the two (almost) the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are almost the same, but RFC3339 (RFC3339 = "2006-01-02T15:04:05Z07:00"
) does not have sub-second precision so it's not ideal for a logger timestamp IMHO.
case cfg.ToSyslog: | ||
sink, err = makeSyslogOutput(cfg) | ||
case cfg.ToFiles: | ||
fallthrough |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for keep teaching me about Golang features 👍
"go.uber.org/zap" | ||
) | ||
|
||
func TestLogger(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding tests 🎉
} | ||
} | ||
|
||
func consoleEncoderConfig() zapcore.EncoderConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should have a base config like the consoleEncoderConfig
and to the changes on top of it the same way you did for the syslogEncoder but also the jsonEncoder? It seems the jsonEncoder has also only 2 differences? Would make it easier to figure out what we do as a "base level" and which changes are specific to a logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree and noticed this myself that there was some duplication. I can clean this up in another PR.
InfoLevel | ||
WarnLevel | ||
ErrorLevel | ||
CriticalLevel // Critical exists only for config backward compatibility. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we use Critical
somewhere in our beats code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We previously supported critical
as a config option so I had to carry it forward (logging.level: critical
). I removed it from the docs.
}, | ||
{ | ||
"checksumSHA1": "JDGx7hehaQunZySwPs7yvdUs2m8=", | ||
"path": "go.uber.org/multierr", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like we have multiple multierr packages? Probably no way around this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, no way other than modifying the third-party software.
No, we made the change to output to file by default a while ago. See #1437
This is a valid concern (though hopefully ERR will still match ERROR). But I really hope the format change doesn't cause too much trouble. 🤞 |
Fantastic to have structured logging in logp! AFAIK, Kibana will use an easily readable logging format depending on whether there's a TTY or not. I haven't had time to look into the implementation here, but it seems like it would be nice to output a human readable format when starting with |
@andrewkroh is this going in 6.2? We'd like to use it |
Interesting idea. That's possibly something we could add for 7.0 (since it's kind of breaking).
I believe so. I think it's just waiting on the next mass merge from master to the 6.x branch. |
This refactors logp and adds support for structured logging. logp uses github.com/uber-go/zap in its implementation. There are no changes to the user facing logging configuration. The logger output will have some format differences, but in general will have a more consistent format across outputs.
Here is some sample output taken from the
TestLogger
test case.Any test code that calls
logp.LogInit()
in libbeat needs to be updated to uselogp.TestingSetup()
.