-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
flb_aws_util: added function flb_aws_strftime_precision for time output #6328
Conversation
@Claych its |
size_t s; | ||
const char *format = "%Y-%m-%dT%H:%M:%S"; | ||
len = strftime(str, maxsize, format, timeptr); | ||
format = strstr(time_key_format, ".%F"); |
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.
why is the user required to put a dot .
character in there? Can we support user provided timestamp formats where the milliseconds do not include a dot?
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.
In my opinion, customers can add millisecond or nanosecond with time_key_format %Y-%m-%dT%H:%M:%S.%F or %Y-%m-%dT%H:%M:%S.%L. because default setting is %Y-%m-%dT%H:%M:%S so I put a dot .
here. Of course we can delete this dot in logic.
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.
The goal of time_key_format is to give the user full control over the timestamp format. If we require that milliseconds or nanoseconds are prefaced with a dot then we are restricting the user unnecessarily IMO. Just because that might be the most common or obvious use case does not mean it is the only one.
13d3554
to
a743d21
Compare
format = strstr(time_key_format, ".%L"); | ||
if (format) { | ||
s = snprintf(str + len, sizeof(str) - 1 - len, | ||
".%09" PRIu64 "Z", |
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.
what does the format var 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.
because you said we can't put function as argument so I reused the format to avoid that happen
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.
Sorry I am not following here- format is a char *, not a function pointer.
format
is set to the return value of strstr but then its not used later in the function... is the goal just to check whether or not the format contains this string? What is the purpose of this variable? Is it a format or something else? What is the most ideal name here?
const char *time_key_format, const struct tm *timeptr, | ||
size_t len, struct flb_time *tms){ | ||
size_t s; | ||
const char *format = "%Y-%m-%dT%H:%M:%S"; |
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.
Wait is format supposed to be the default format? Sorry I am very confused here.
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.
"%Y-%m-%dT%H:%M:%S.%L" => "2022-11 ... 12:30:45.%L" =>
"%Y-%m-%dT%H:%M:%S.%L" => "%Y-%m-%dT%H:%M:%S.23923942332" => strftime
} else { | ||
format = strstr(time_key_format, ".%L"); | ||
if (format) { | ||
s = snprintf(str + len, sizeof(str) - 1 - len, |
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.
So len is the number of bytes that strftime wrote... if I am understanding this correctly, then it is just appending the nanoseconds or milliseconds at the end and also a "Z" character. Will it always add a "Z" at the end?
Can this code handle timestamps where there is no Z at the end or where the nanoseconds are not at the end? For example. what if the timestamp is backwards to our normal order, with nanosecond, then second, then minute, etc
a743d21
to
38ce39e
Compare
b9566fb
to
d4113ad
Compare
#define millisecond_length 4 | ||
#define nanosecond_length 10 | ||
#define milli_string_old "%F" | ||
#define nano_string_old "%L" |
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.
these should to be prefixed with FLB and need to have good long descriptive names once they are moved to the flb_aws_util.c
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.
IIRC this is because in C, everything is global basically, so all these constants have to have unique names I think
{ | ||
char millisecond_string[millisecond_length]; | ||
char nanosecond_string[nanosecond_length]; | ||
/* calculate the length of str, replace %F to 3 digits and %L to 9 digits */ |
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: replace "str" with out_buff
char millisecond_string[millisecond_length]; | ||
char nanosecond_string[nanosecond_length]; | ||
/* calculate the length of str, replace %F to 3 digits and %L to 9 digits */ | ||
out_size = strlen(time_key_format)+count_substring(time_key_format, milli_string_old)+7*count_substring(time_key_format, nano_string_old); |
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 still do not understand the math here, why 7 * the nano string but just 1 * the milli string? We can discuss if 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.
Is 7 a special number such that it could be a constant?
mem_for_time_key_format = (char *)calloc(strlen(time_key_format), sizeof(char)); | ||
tem_buff_time_str = (char *)calloc(out_size, sizeof(char)); | ||
out_buff = (char *)calloc(out_size, sizeof(char)); |
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.
every time you alloc, you need to check if it succeeded or not and have error handling
/* | ||
* Adjust the time_key output format according to time_key_format. | ||
*/ | ||
static void create_time_format_string(char *out_buff, size_t out_size, |
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.
Should be: char **out_buff, size_t *out_size,
since these are used to get output from the function
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.
remember what i said about the out_buf pattern? Look up the int flb_gzip_compress(void *in_data, size_t in_len, void **out_data, size_t *out_len)
function as an example of this in existing code
snprintf(nanosecond_string, nanosecond_length, "%" PRIu64, (uint64_t) tms->tm.tv_nsec); | ||
for (int i = 0; i < strlen(time_key_format); i++) { | ||
if (!strncmp(time_key_format + i, milli_string_old, strlen(milli_string_old))) { | ||
strcat(tem_buff_time_str, millisecond_string); |
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.
let's always use strncat since its safer
strcat(tem_buff_time_str, millisecond_string); | ||
i += strlen(milli_string_old) - 1; | ||
} else if (!strncmp(time_key_format + i, nano_string_old, strlen(nano_string_old))) { | ||
strcat(tem_buff_time_str, nanosecond_string); |
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.
strncat plz
5521109
to
8f5a5c7
Compare
f904861
to
2a109bf
Compare
fec66d0
to
8b0fea0
Compare
891b81b
to
597b615
Compare
Signed-off-by: Clay Cheng <[email protected]>
…e output. Signed-off-by: Clay Cheng <[email protected]>
…me output. Signed-off-by: Clay Cheng <[email protected]>
b37274c
to
f97cafc
Compare
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.
Assuming this is fully tested I think we are good to go.
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.
This looks good. Please address Wesley's comment though. If this is well tested, then it still has my approval for merge.
out_size = strftime(buf, tmp_parsed_time_str_len, | ||
tmp_parsed_time_str, ×tamp); | ||
|
||
/* Check whether tmp_parsed_time_str_len is enough for tmp_out_buff */ |
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.
Please address this comment
if (out_size == 0) { | ||
flb_free(tmp_parsed_time_str); | ||
flb_free(buf); | ||
return 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.
Sorry I missed this before- why is the function returning 0 to indicate failure?
This breaks the pattern of FLB code. We usually use -1 to indicate failure and 0 to indicate success for function integer returns.
I see that strftime returns 0 if it fails, however, to match FLB code practices, I think we should have this function return -1 in that case to make it easy for the caller to understand.
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.
Sorry I forgot that size_t is an unsigned type so we have to use 0 as return value for error. So this makes sense.
…uent#6328) Signed-off-by: Clay Cheng <[email protected]> Signed-off-by: root <[email protected]>
Enter
[N/A]
in the box, if an item is not applicable to your change.Testing
Before we can approve your change; please submit the following in a comment:
Normal time_key_format
Wrong time_key_format
fluent-bit log
If this is a change to packaging of containers or native binaries then please confirm it works for all targets.
Documentation
fluent/fluent-bit-docs#981 fluent/fluent-bit-docs#980
Backporting
Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.