-
-
Notifications
You must be signed in to change notification settings - Fork 4k
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
perf: use zap's Check() to prevent useless allocs #6560
Conversation
modules/caddyhttp/server.go
Outdated
repl.Set("http.response.status", status) // will be 0 if no response is written by us (Go will write 200 to client) | ||
repl.Set("http.response.size", size) | ||
repl.Set("http.response.duration", duration) | ||
repl.Set("http.response.duration_ms", duration.Seconds()*1e3) // multiply seconds to preserve decimal (see #4666) |
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'm not sure if it's correct to sometimes not set the replacer. It has side effects, it's not only used in logging.
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 is already not in some cases:
https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/server.go#L757-L760
Should we always set them?
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 restored the previous behavior, but maybe should we set the replacer before the existing guard clause
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.
(benchmark updated)
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 so much for contributing this, @dunglas! Can't wait to try this out :)
I think this isn't working correctly. I have There must be some layer of inversion somewhere which prevents |
Oh sorry I'm an absolute dummy, the |
I am seeing the use of zap.Error() in cases where the previous line contains a check for zap.Warnlevel in a few of these changes, which surely looks like a mistake to me, as it changes the level of the log line to error where previously a warning was used. At least the issuing of error messages for writing errors is back, the pull request #6532 does not have any effect any longer. |
@jum could you make a PR to fix those cases you see? Thanks for taking a look! |
I am not that familiar with zap logging, but looking at the source code of zap it should not happen at all. The Check function records the level that is being checked and uses it on ce.Write, but still I do get these "aborting with incomplete response" messages on ErrorLevel. Anyone any clue how that is possible? |
Ok, ignore these comments from me above. I had a small error in my CI and I build accidentally against "latest" instead of "master", I checked my docker container and it has 2.8.4 as the version, way before the patches. Sorry. |
It happens. Thanks! |
Zap provides an optional API to prevent allocating fields that will never be used because the configured log level is higher than the emitted log.
We had good results using this trick in Mercure and more recently in FrankenPHP. This is also the trick that has been used in #6541.
This is especially important for
DEBUG
andINFO
level logs (which are usually disabled in production), as well as for benchmarks (where logs are usually entirely disabled).As you can see in the added benchmark, this significantly improves performance:
Before (no logs):
After (no logs):
Our FrankenPHP benchmarks show that the server can handle ~1% more requests per second by applying this patch (a Hello World page). In some cases, the performance gain can be more important (streaming for instance, which logs many things at the
DEBUG
level).The optimized syntax is a bit more verbose, but not that much IMHO.