-
Notifications
You must be signed in to change notification settings - Fork 625
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 #1022
base: unstable
Are you sure you want to change the base?
Conversation
Signed-off-by: azuredream <[email protected]>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## unstable #1022 +/- ##
============================================
+ Coverage 70.61% 70.65% +0.03%
============================================
Files 114 114
Lines 61734 63125 +1391
============================================
+ Hits 43595 44602 +1007
- Misses 18139 18523 +384
|
😀 thanks for opening this, we're working on launching the next version but will take a look shortly. |
I like this change. Free-form log lines can be tricky to parse and search, and this feels like a good step toward adopting more structured logging. We could even extend it further to include properties like "area" (e.g., "cluster," "normal replication," "dual channel replication," etc.). Thanks for your work on this, @azuredream! |
Signed-off-by: azuredream <[email protected]>
@valkey-io/core-team Please indicate your vote on this comment. The open questions I still have are if we want to also do the larger investigation before 8.1 launches about also including the component the log was generated from. We also have the JSON format to add on. |
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've reviewed this before in the open source redis time. I like it, just a few comments.
It seems that JSON is more popular. We can add that too in another PR.
Configurable time format is good.
src/config.c
Outdated
configEnum log_timestamp_format_enum[] = {{"default", LOG_TIMESTAMP_DEFAULT}, | ||
{"iso8601", LOG_TIMESTAMP_ISO8601}, | ||
{"unix", LOG_TIMESTAMP_UNIX}, |
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.
configEnum log_timestamp_format_enum[] = {{"default", LOG_TIMESTAMP_DEFAULT}, | |
{"iso8601", LOG_TIMESTAMP_ISO8601}, | |
{"unix", LOG_TIMESTAMP_UNIX}, | |
configEnum log_timestamp_format_enum[] = {{"legacy", LOG_TIMESTAMP_LEGACY}, | |
{"iso8601", LOG_TIMESTAMP_ISO8601}, | |
{"milliseconds", LOG_TIMESTAMP_MILLISECONDS}, |
@azuredream Was there a reason we added the unix milliseconds timestamp option? While discussing it, we weren't sure if it was needed.
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 PR currently emits it as seconds, not milliseconds, since the epoch.)
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.
If we want the epoch, I think millisecond timestamp makes a lot more sense. A lot of important events happen sub-second.
src/server.c
Outdated
snprintf(buf + off, sizeof(buf) - off, "%03d%s", (int)tv.tv_usec / 1000, tzbuf); | ||
break; | ||
|
||
case LOG_TIMESTAMP_UNIX: snprintf(buf, sizeof(buf), "%ld", tv.tv_sec); break; |
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 should be in milliseconds, not seconds.
@madolson @zuiderkwast |
Signed-off-by: azuredream <[email protected]>
Demo logs: log-format logfmt
log-format legacy
log-format logfmt
log-format legacy
log-format logfmt
log-format legacy
|
Signed-off-by: azuredream <[email protected]>
Signed-off-by: azuredream <[email protected]>
src/server.c
Outdated
/* Low level logging. To use only for very big messages, otherwise | ||
* serverLog() is to prefer. */ | ||
void serverLogRaw(int level, const char *msg) { | ||
void serverLogRaw(int level, char *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.
Mutability modified.
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.
Hm... I hope this works. I see many places in the code where this function is called with a string literal, like
serverLogRaw(LL_WARNING, "Failed applying new module configuration. Restoring previous settings.");
This can't be mutable, I think...
src/server.c
Outdated
while (msg[src] != '\0') { | ||
if (msg[src] == '"') { | ||
msg[dst++] = '\''; | ||
} else if (msg[src] != '\n' && msg[src] != '\r') { | ||
msg[dst++] = msg[src]; | ||
} | ||
src++; |
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.
Just an idea: If we replace \r
and \n
with a space instead, then we don't need to copy/move the rest of the string. We don't need the dst
index.
while (msg[src] != '\0') { | |
if (msg[src] == '"') { | |
msg[dst++] = '\''; | |
} else if (msg[src] != '\n' && msg[src] != '\r') { | |
msg[dst++] = msg[src]; | |
} | |
src++; | |
while (msg[src] != '\0') { | |
if (msg[src] == '"') { | |
msg[src] = '\''; | |
} else if (msg[src] == '\n' && msg[src] == '\r') { | |
msg[src] = ' '; | |
} | |
src++; |
Signed-off-by: azuredream <[email protected]>
Code updateded. |
Signed-off-by: azuredream <[email protected]>
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.
Looks good to me now.
One of the commits is missing sign-off. See the Details link on the DCO CI job. Can you fix it? You can squash and force-push as you want.
See also the clang-format CI job. It's a trailing whitespace on one line.
Is the Valkey logo logged on startup? It must look very weird with logfmt?
} else { | ||
role_char = (server.primary_host ? 'S' : 'M'); /* replica or Primary. */ | ||
role_index = (server.primary_host ? 2 : 3); /* Slave or Master. */ |
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.
Nit: We should avoid slave and master even in comments.
role_index = (server.primary_host ? 2 : 3); /* Slave or Master. */ | |
role_index = (server.primary_host ? 2 : 3); /* replica or primary. */ |
See more disscussion:
redis/redis#12934
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.#1006