Configuration option to output logs in logfmt#12934
Configuration option to output logs in logfmt#12934azuredream wants to merge 17 commits intoredis:unstablefrom
Conversation
Signed-off-by: azuredream <[email protected]>
zuiderkwast
left a comment
There was a problem hiding this comment.
@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.
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.
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.
Thanks for your review!
I suppose the questions are for @madolson. I'll wait for his reply.
There was a problem hiding this comment.
@azuredream The questions are for you. :) What do you think?
There was a problem hiding this comment.
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.
@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.
@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.
@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.
Yes at runtime. Or replace with \". What else can we do?
There was a problem hiding this comment.
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 <[email protected]>
|
Added timestamp_format enum. |
|
Signed-off-by: azuredream <[email protected]>
Signed-off-by: azuredream <[email protected]>
Signed-off-by: azuredream <[email protected]>
|
Hi @zuiderkwast. Any comment on this PR? |
zuiderkwast
left a comment
There was a problem hiding this comment.
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 <[email protected]>
|
Thanks for your review. Updated. |
Signed-off-by: azuredream <[email protected]>
| break; | ||
| } | ||
|
|
||
| switch (server.log_format) { |
There was a problem hiding this comment.
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.
I think this approach is sensible enough.
There was a problem hiding this comment.
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 <[email protected]>
|
@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. |
|
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 <[email protected]>
Signed-off-by: azuredream <[email protected]>
|
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.
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.
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 <[email protected]>
Signed-off-by: azuredream <[email protected]>
|
no movement here? it's been almost a year and this PR has now been backlogged, so what's the timeframe for this if you have one? |
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