Skip to content

Commit b02cb10

Browse files
authored
pack: added java_sql_timestamp format (#4811)
* pack: added java_sql_timestamp, a format string used by amazon athena This commit adds a new timestamp format, the java_sql_timestamp, which is very similar to iso8601, except that it has a space instead of a T between the date and the hour and does not end with Z (or any other timestamp delimiter) This is the format: "%Y-%m-%d %H:%M:%S" This is unfortunatelly the only format accepted by Amazon Athena. Signed-off-by: Marcos Diez <[email protected]>
1 parent 3e1be8b commit b02cb10

File tree

8 files changed

+51
-25
lines changed

8 files changed

+51
-25
lines changed

DEVELOPER_GUIDE.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,10 @@ Config maps are an improvement to the previous Fluent Bit API that was used by p
429429

430430
There are various types of supported configuration types. Full list available [here](https://github.com/fluent/fluent-bit/blob/v1.4.2/include/fluent-bit/flb_config_map.h#L29). The most used ones are:
431431

432-
| Type | Description |
433-
| -----------------------|:---------------------:|
434-
| FLB_CONFIG_MAP_INT | Represents integer data type |
435-
| FLB_CONFIG_MAP_BOOL | Represents boolean data type |
432+
| Type | Description |
433+
| -----------------------|:---------------------:|
434+
| FLB_CONFIG_MAP_INT | Represents integer data type |
435+
| FLB_CONFIG_MAP_BOOL | Represents boolean data type |
436436
| FLB_CONFIG_MAP_DOUBLE | Represents a double |
437437
| FLB_CONFIG_MAP_SIZE | Provides size_type as an integer datatype large enough to represent any possible string size. |
438438
| FLB_CONFIG_MAP_STR | Represents string data type |
@@ -441,8 +441,8 @@ There are various types of supported configuration types. Full list available [h
441441

442442
A config map expects certain public fields at registration.
443443

444-
| Public Fields | Description |
445-
| --------------|:---------------------|
444+
| Public Fields | Description |
445+
| --------------|:---------------------|
446446
| Type | This field is the data type of the property that we are writing to the config map. If the property is of type `int` we use `FLB_CONFIG_MAP_INT`, if `string` `FLB_CONFIG_MAP_STR` etc. |
447447
| Name | This field is the name of the configuration property. For example for the property flush count we use `flush_count`|
448448
| Default Value | This field allows the user to set the default value of the property. For example, for a property of type `FLB_CONFIG_MAP_BOOL` (boolean), the default value may be false. Then we have to give `false` as default value. If there is no default value, `NULL` is given.|
@@ -469,7 +469,7 @@ static struct flb_config_map config_map[] = {
469469
{
470470
FLB_CONFIG_MAP_STR, "json_date_key", "date",
471471
0, FLB_TRUE, offsetof(struct flb_stdout, json_date_key),
472-
"Specifies the format of the date. Supported formats are double, iso8601 and epoch."
472+
"Specifies the format of the date. Supported formats are double, iso8601, java_sql_timestamp and epoch."
473473
},
474474

475475
/* EOF */

include/fluent-bit/flb_pack.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,23 @@
3535
#define FLB_PACK_JSON_PRIMITIVE JSMN_PRIMITIVE
3636

3737
/* Date formats */
38-
#define FLB_PACK_JSON_DATE_DOUBLE 0
39-
#define FLB_PACK_JSON_DATE_ISO8601 1
40-
#define FLB_PACK_JSON_DATE_EPOCH 2
38+
#define FLB_PACK_JSON_DATE_DOUBLE 0
39+
#define FLB_PACK_JSON_DATE_ISO8601 1
40+
#define FLB_PACK_JSON_DATE_EPOCH 2
41+
#define FLB_PACK_JSON_DATE_JAVA_SQL_TIMESTAMP 3
4142

4243
/* Specific ISO8601 format */
4344
#define FLB_PACK_JSON_DATE_ISO8601_FMT "%Y-%m-%dT%H:%M:%S"
4445

46+
/* Specific Java SQL Timestamp format */
47+
#define FLB_PACK_JSON_DATE_JAVA_SQL_TIMESTAMP_FMT "%Y-%m-%d %H:%M:%S"
48+
49+
#define FBL_PACK_JSON_DATE_FORMAT_DESCRIPTION "Specify the format of the date, " \
50+
"supported formats: double, " \
51+
"iso8601 (e.g: 2018-05-30T09:39:52.000681Z), " \
52+
"java_sql_timestamp (e.g: 2018-05-30 09:39:52.000681, useful for AWS Athena), "\
53+
"and epoch."
54+
4555
/* JSON formats (modes) */
4656
#define FLB_PACK_JSON_FORMAT_NONE 0
4757
#define FLB_PACK_JSON_FORMAT_JSON 1

plugins/out_http/http.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ static struct flb_config_map config_map[] = {
390390
{
391391
FLB_CONFIG_MAP_STR, "json_date_format", NULL,
392392
0, FLB_FALSE, 0,
393-
"Specify the format of the date. Supported formats are 'double' and 'iso8601'"
393+
FBL_PACK_JSON_DATE_FORMAT_DESCRIPTION
394394
},
395395
{
396396
FLB_CONFIG_MAP_STR, "json_date_key", "date",

plugins/out_null/null.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ static struct flb_config_map config_map[] = {
146146
{
147147
FLB_CONFIG_MAP_STR, "json_date_key", "date",
148148
0, FLB_TRUE, offsetof(struct flb_null, json_date_key),
149-
"Specifies the format of the date. Supported formats are double, iso8601 and epoch."
149+
FBL_PACK_JSON_DATE_FORMAT_DESCRIPTION
150150
},
151151

152152
/* EOF */

plugins/out_s3/s3.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ static int create_headers(struct flb_s3 *ctx, char *body_md5, struct flb_aws_hea
146146
*headers = s3_headers;
147147
return 0;
148148
}
149-
149+
150150
s3_headers = flb_malloc(sizeof(struct flb_aws_header) * headers_len);
151151
if (s3_headers == NULL) {
152152
flb_errno();
@@ -174,7 +174,7 @@ static int create_headers(struct flb_s3 *ctx, char *body_md5, struct flb_aws_hea
174174
s3_headers[n].val = body_md5;
175175
s3_headers[n].val_len = strlen(body_md5);
176176
}
177-
177+
178178
*num_headers = headers_len;
179179
*headers = s3_headers;
180180
return 0;
@@ -374,7 +374,7 @@ static int init_seq_index(void *context) {
374374
flb_plg_error(ctx->ins, "Failed to write to sequential index metadata file");
375375
return -1;
376376
}
377-
}
377+
}
378378
else {
379379
ret = read_seq_index(ctx->seq_index_file, &ctx->seq_index);
380380
if (ret < 0) {
@@ -725,7 +725,7 @@ static int cb_s3_init(struct flb_output_instance *ins,
725725
tmp = flb_output_get_property("compression", ins);
726726
if (tmp) {
727727
if (ctx->use_put_object == FLB_FALSE) {
728-
flb_plg_error(ctx->ins,
728+
flb_plg_error(ctx->ins,
729729
"use_put_object must be enabled when compression is enabled");
730730
return -1;
731731
}
@@ -1366,7 +1366,7 @@ static int s3_put_object(struct flb_s3 *ctx, const char *tag, time_t create_time
13661366
return -1;
13671367
}
13681368
}
1369-
1369+
13701370
s3_client = ctx->s3_client;
13711371
if (s3_plugin_under_test() == FLB_TRUE) {
13721372
c = mock_s3_call("TEST_PUT_OBJECT_ERROR", "PutObject");
@@ -1872,7 +1872,7 @@ static flb_sds_t flb_pack_msgpack_extract_log_key(void *out_context, const char
18721872
}
18731873

18741874
msgpack_unpacked_init(&result);
1875-
while (!alloc_error &&
1875+
while (!alloc_error &&
18761876
msgpack_unpack_next(&result, data, bytes, &off) == MSGPACK_UNPACK_SUCCESS) {
18771877
/* Each array must have two entries: time and record */
18781878
root = result.data;
@@ -1914,7 +1914,7 @@ static flb_sds_t flb_pack_msgpack_extract_log_key(void *out_context, const char
19141914
if (strncmp(ctx->log_key, key_str, key_str_size) == 0) {
19151915
found = FLB_TRUE;
19161916

1917-
/*
1917+
/*
19181918
* Copy contents of value into buffer. Necessary to copy
19191919
* strings because flb_msgpack_to_json does not handle nested
19201920
* JSON gracefully and double escapes them.
@@ -1932,7 +1932,7 @@ static flb_sds_t flb_pack_msgpack_extract_log_key(void *out_context, const char
19321932
val_offset++;
19331933
}
19341934
else {
1935-
ret = flb_msgpack_to_json(val_buf + val_offset,
1935+
ret = flb_msgpack_to_json(val_buf + val_offset,
19361936
msgpack_size - val_offset, &val);
19371937
if (ret < 0) {
19381938
break;
@@ -1955,7 +1955,7 @@ static flb_sds_t flb_pack_msgpack_extract_log_key(void *out_context, const char
19551955

19561956
/* Throw error once per chunk if at least one log key was not found */
19571957
if (log_key_missing == FLB_TRUE) {
1958-
flb_plg_error(ctx->ins, "Could not find log_key '%s' in %d records",
1958+
flb_plg_error(ctx->ins, "Could not find log_key '%s' in %d records",
19591959
ctx->log_key, log_key_missing);
19601960
}
19611961

@@ -2241,7 +2241,7 @@ static struct flb_config_map config_map[] = {
22412241
{
22422242
FLB_CONFIG_MAP_STR, "json_date_format", NULL,
22432243
0, FLB_FALSE, 0,
2244-
"Specifies the format of the date. Supported formats are double, iso8601 and epoch."
2244+
FBL_PACK_JSON_DATE_FORMAT_DESCRIPTION
22452245
},
22462246
{
22472247
FLB_CONFIG_MAP_STR, "json_date_key", "date",

plugins/out_stdout/stdout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ static struct flb_config_map config_map[] = {
209209
{
210210
FLB_CONFIG_MAP_STR, "json_date_format", NULL,
211211
0, FLB_FALSE, 0,
212-
"Specifies the format of the date. Supported formats are double, iso8601 and epoch."
212+
FBL_PACK_JSON_DATE_FORMAT_DESCRIPTION
213213
},
214214
{
215215
FLB_CONFIG_MAP_STR, "json_date_key", "date",

plugins/out_tcp/tcp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,7 @@ static struct flb_config_map config_map[] = {
124124
{
125125
FLB_CONFIG_MAP_STR, "json_date_format", "double",
126126
0, FLB_FALSE, 0,
127-
"Specify the format of the date, supported formats: double, iso8601 "
128-
"(e.g: 2018-05-30T09:39:52.000681Z) and epoch."
127+
FBL_PACK_JSON_DATE_FORMAT_DESCRIPTION
129128
},
130129

131130
{

src/flb_pack.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,9 @@ int flb_pack_to_json_date_type(const char *str)
799799
if (strcasecmp(str, "double") == 0) {
800800
return FLB_PACK_JSON_DATE_DOUBLE;
801801
}
802+
else if (strcasecmp(str, "java_sql_timestamp") == 0) {
803+
return FLB_PACK_JSON_DATE_JAVA_SQL_TIMESTAMP;
804+
}
802805
else if (strcasecmp(str, "iso8601") == 0) {
803806
return FLB_PACK_JSON_DATE_ISO8601;
804807
}
@@ -908,6 +911,20 @@ flb_sds_t flb_pack_msgpack_to_json_format(const char *data, uint64_t bytes,
908911
case FLB_PACK_JSON_DATE_DOUBLE:
909912
msgpack_pack_double(&tmp_pck, flb_time_to_double(&tms));
910913
break;
914+
case FLB_PACK_JSON_DATE_JAVA_SQL_TIMESTAMP:
915+
/* Format the time, use microsecond precision not nanoseconds */
916+
gmtime_r(&tms.tm.tv_sec, &tm);
917+
s = strftime(time_formatted, sizeof(time_formatted) - 1,
918+
FLB_PACK_JSON_DATE_JAVA_SQL_TIMESTAMP_FMT, &tm);
919+
920+
len = snprintf(time_formatted + s,
921+
sizeof(time_formatted) - 1 - s,
922+
".%06" PRIu64,
923+
(uint64_t) tms.tm.tv_nsec / 1000);
924+
s += len;
925+
msgpack_pack_str(&tmp_pck, s);
926+
msgpack_pack_str_body(&tmp_pck, time_formatted, s);
927+
break;
911928
case FLB_PACK_JSON_DATE_ISO8601:
912929
/* Format the time, use microsecond precision not nanoseconds */
913930
gmtime_r(&tms.tm.tv_sec, &tm);

0 commit comments

Comments
 (0)