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
Configuration option to output logs in logfmt #12934
base: unstable
Are you sure you want to change the base?
Conversation
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
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.
@azuredream Thanks, it's a good start. Let's see if the core team will accept this.
@madolson do you like the idea of a configurable logging format?
src/server.c
Outdated
if(server.logfmt) { | ||
fprintf(fp,"pid=%d role_char=%c timestamp=\"%s\" level=%c message=\"%s\"\n", | ||
(int)getpid(),role_char, buf,c[level],msg); |
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 suggest role=%c
(instead of role_char=%c
). Is one char clear enough? If not, we can consider using role=master, role=sentinel, etc. but it makes the log longer. Maybe one char is clear enough?
For the level, maybe it would be more normal to use the words warning
, notice
, info
, debug
instead of the symbols?
Do we need to check if msg
contains double quotes and linebreaks and escape those?
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.
One more thing: I think the timestamp should be in ISO format, like 2024-01-11T10:34:38.000Z
(always in UTC or with another timezone, i'm not sure what's best...)
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 your review!
I suppose the questions are for @madolson. I'll wait for his reply.
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.
@azuredream The questions are for you. :) What do you think?
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 actually have a slightly different opinion, which is that I think the strftime format for timestamps should be configurable. It's easiest to test and validate, and I've seen various asks for it to be in a slight different format over time.
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.
@madolson the log in debug.c you linked prints the argv, which can be a key name.
Correct, it's on my list of stuff I would like to remove. It was vaguely on my radar as one of the things to fix with https://github.com/redis/redis/pulls?q=is%3Apr+is%3Aopen+redact.
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.
@madolson Ah, so do we need to get #11747 merged before we can proceed with this and avoid escaping stuff in message? (I don't like that PRs are blocked by other PRs. Maybe we can just change "
to '
in that log entry for now?)
For modules logging, can we simply replace "
with '
in-place in moduleLogRaw?
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.
@madolson Ah, so do we need to get #11747 merged before we can proceed with this and avoid escaping stuff in message? (I don't like that PRs are blocked by other PRs. Maybe we can just change " to ' in that log entry for now?)
Let's do as you suggested for the moment. Let's also make a debug assertion so we never add the "
for any logs.
For modules logging, can we simply replace " with ' in-place in moduleLogRaw?
Like at runtime? I suppose that works, but is also a bit of a breaking change.
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 at runtime. Or replace with \"
. What else can we do?
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 at runtime. Or replace with ". What else can we do?
I suppose we probably need to do that now.
Also just wanted to mention #12932 for reference. |
Does this mean we will have two new configs, one for enabling json logfmt, another one for selecting timestamp format? |
I don't have a great alternative suggestion without making a complex configuration argument. |
Regarding timestamps #12932, I guess most of the time user would like to see millisecond or microseconds resolution, a configurable Even today redis source code adds the milliseconds outside the Lines 138 to 139 in 9d0158b
So then you would need to create your own extended "format specification" supporting "%f" for microseconds (like python does) and to hide differences between Summarizing the issues with
To me it seems simpler to enforce a ISO 8601 with microsecond resolution and utc offset:
|
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Added timestamp_format enum. |
|
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Hi @zuiderkwast. Any comment on this PR? |
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 OK with the config, but it is marked with major-decision
which means the core team will need to decide about the config in a meeting. (I'm not in the core team.)
Maybe it's better to wait until the config has been decided before changing the details of the code.
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Thanks for your review. Updated. |
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
break; | ||
} | ||
|
||
switch (server.log_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.
There are 6 combinations of log_format X role. Could be more moving forward. This is another way to code the logic, but I'm not sure if it's the "better" way...
It does keep the minimum memory usage for role print though.
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 approach is sensible enough.
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 could do like we do for verbosity level. For the legacy format we pick a char from "XCSM" and for logfmt a string from an array, same index.
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
@azuredream Thanks for all your involvement, we'll discuss it tomorrow and give directional input if this is the best format for it to be accepted. Thanks for all your help so far. |
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Hi @madolson. Thanks for review. I just updated my PR based on your suggestions. |
@redis/core-team Please review the two configurations at the top for a high level approval. There is one pending question, which is what to do about module logging that might inject |
can someone edit the top comment to provide some overview of the differences (examples), as well as justification for this feature? |
Thanks to @zuiderkwast for updating the top comment. |
PR updated. |
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Not sure how to make |
i still don't see the top comment mentions the justification. our log file isn't an API, and for the most part we feel free to add / remove rephrase messages, or change their log level, so i wonder why would someone want to parse by software. |
src/server.c
Outdated
snprintf(buf+off,sizeof(buf)-off,"%03d",(int)tv.tv_usec/1000); | ||
char tzbuf[6]; | ||
strftime(tzbuf, sizeof(tzbuf), "%z", &tm); | ||
char tz_formatted[7]; | ||
snprintf(tz_formatted, sizeof(tz_formatted), "%c%c%c:%c%c", tzbuf[0], tzbuf[1], tzbuf[2], tzbuf[3], tzbuf[4]); | ||
strncat(buf, tz_formatted, sizeof(buf) - strlen(buf) - 1); |
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.
Good, but maybe we can do it with only one snprintf
for milliseconds and time zone?
snprintf(buf+off,sizeof(buf)-off,"%03d",(int)tv.tv_usec/1000); | |
char tzbuf[6]; | |
strftime(tzbuf, sizeof(tzbuf), "%z", &tm); | |
char tz_formatted[7]; | |
snprintf(tz_formatted, sizeof(tz_formatted), "%c%c%c:%c%c", tzbuf[0], tzbuf[1], tzbuf[2], tzbuf[3], tzbuf[4]); | |
strncat(buf, tz_formatted, sizeof(buf) - strlen(buf) - 1); | |
char tzbuf[6]; | |
strftime(tzbuf, sizeof(tzbuf), "%z", &tm); | |
snprintf(buf + off, sizeof(buf) - off, "%03d%c%c%c:%c%c", | |
(int)tv.tv_usec/1000, | |
tzbuf[0], tzbuf[1], tzbuf[2], tzbuf[3], tzbuf[4]); |
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. Updated as your suggestion.
@oranagra The motivation is in the linked issue #12918. I thought it was linked before but it wasn't so I linked it now. @azuredream Hint for another time: Include |
Thanks! I linked two issues that may be closed by this PR |
I have no opinion to logfmt (neither supporting nor opposing), but I do believe that time zone information is useful. It helps to determine the actual time when deploying globally. Another PR #12939 has been submitted separately to add time zone information. |
@redis/core-team There are three more or less orthogonal things to take decisions about here:
You may want to decide about each of these separately. |
Implemented a function to populate timezone string since
|
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Signed-off-by: azuredream <zhaozixuan67@gmail.com>
Add ability to configure Redis to output logs in logfmt (See https://brandur.org/logfmt) as well as configure timestamp format options to more standard ISO 8601 or unix timestamp.
This change is implemented by two configs:
log-format
: Either default or logfmt.log-timestamp-format
: default, iso8601, or unix.iso8601 includes time zone.
Closes #12918
Closes #12932