Skip to content

Commit 1059bee

Browse files
PettitWesleyedsiper
authored andcommitted
out_cloudwatch_logs: support log_group_class option
Signed-off-by: Wesley Pettit <[email protected]>
1 parent faadf3d commit 1059bee

File tree

3 files changed

+94
-18
lines changed

3 files changed

+94
-18
lines changed

plugins/out_cloudwatch_logs/cloudwatch_api.c

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,21 +1285,39 @@ int create_log_group(struct flb_cloudwatch *ctx, struct log_stream *stream)
12851285

12861286
flb_plg_info(ctx->ins, "Creating log group %s", stream->group);
12871287

1288-
body = flb_sds_create_size(25 + strlen(stream->group));
1289-
if (!body) {
1290-
flb_sds_destroy(body);
1291-
flb_errno();
1292-
return -1;
1293-
}
1294-
12951288
/* construct CreateLogGroup request body */
1296-
tmp = flb_sds_printf(&body, "{\"logGroupName\":\"%s\"}", stream->group);
1297-
if (!tmp) {
1298-
flb_sds_destroy(body);
1299-
flb_errno();
1300-
return -1;
1289+
if (ctx->log_group_class_type == LOG_CLASS_DEFAULT_TYPE) {
1290+
body = flb_sds_create_size(30 + strlen(stream->group));
1291+
if (!body) {
1292+
flb_sds_destroy(body);
1293+
flb_errno();
1294+
return -1;
1295+
}
1296+
1297+
tmp = flb_sds_printf(&body, "{\"logGroupName\":\"%s\"}", stream->group);
1298+
if (!tmp) {
1299+
flb_sds_destroy(body);
1300+
flb_errno();
1301+
return -1;
1302+
}
1303+
body = tmp;
1304+
} else {
1305+
body = flb_sds_create_size(37 + strlen(stream->group) + strlen(ctx->log_group_class));
1306+
if (!body) {
1307+
flb_sds_destroy(body);
1308+
flb_errno();
1309+
return -1;
1310+
}
1311+
1312+
tmp = flb_sds_printf(&body, "{\"logGroupName\":\"%s\", \"logGroupClass\":\"%s\"}",
1313+
stream->group, ctx->log_group_class);
1314+
if (!tmp) {
1315+
flb_sds_destroy(body);
1316+
flb_errno();
1317+
return -1;
1318+
}
1319+
body = tmp;
13011320
}
1302-
body = tmp;
13031321

13041322
if (plugin_under_test() == FLB_TRUE) {
13051323
c = mock_http_call("TEST_CREATE_LOG_GROUP_ERROR", "CreateLogGroup");
@@ -1316,7 +1334,8 @@ int create_log_group(struct flb_cloudwatch *ctx, struct log_stream *stream)
13161334

13171335
if (c->resp.status == 200) {
13181336
/* success */
1319-
flb_plg_info(ctx->ins, "Created log group %s", stream->group);
1337+
flb_plg_info(ctx->ins, "Created log group %s with storage class %s",
1338+
stream->group, ctx->log_group_class);
13201339
flb_sds_destroy(body);
13211340
flb_http_client_destroy(c);
13221341
ret = set_log_group_retention(ctx, stream);
@@ -1328,8 +1347,16 @@ int create_log_group(struct flb_cloudwatch *ctx, struct log_stream *stream)
13281347
error = flb_aws_error(c->resp.payload, c->resp.payload_size);
13291348
if (error != NULL) {
13301349
if (strcmp(error, ERR_CODE_ALREADY_EXISTS) == 0) {
1331-
flb_plg_info(ctx->ins, "Log Group %s already exists",
1332-
stream->group);
1350+
if (ctx->log_group_class_type == LOG_CLASS_INFREQUENT_ACCESS_TYPE) {
1351+
flb_plg_warn(ctx->ins, "Log Group %s already exists; "
1352+
"Fluent Bit did not create this group in this execution. "
1353+
"Fluent Bit therefore was unable verify or set %s storage. "
1354+
"Check CloudWatch Console or API for the groups storage class status.",
1355+
stream->group, LOG_CLASS_INFREQUENT_ACCESS);
1356+
} else {
1357+
flb_plg_info(ctx->ins, "Log Group %s already exists",
1358+
stream->group);
1359+
}
13331360
flb_sds_destroy(body);
13341361
flb_sds_destroy(error);
13351362
flb_http_client_destroy(c);
@@ -1480,7 +1507,6 @@ int put_log_events(struct flb_cloudwatch *ctx, struct cw_flush *buf,
14801507

14811508
struct flb_http_client *c = NULL;
14821509
struct flb_aws_client *cw_client;
1483-
flb_sds_t tmp;
14841510
int num_headers = 1;
14851511
int retry = FLB_TRUE;
14861512

@@ -1510,7 +1536,7 @@ int put_log_events(struct flb_cloudwatch *ctx, struct cw_flush *buf,
15101536
flb_plg_debug(ctx->ins, "PutLogEvents http status=%d", c->resp.status);
15111537

15121538
if (c->resp.status == 200) {
1513-
if (c->resp.data == NULL || c->resp.data_len == 0 || strstr(c->resp.data, AMZN_REQUEST_ID_HEADER) == NULL) {
1539+
if (c->resp.data == NULL || c->resp.data_len == 0 || strcasestr(c->resp.data, AMZN_REQUEST_ID_HEADER) == NULL) {
15141540
/* code was 200, but response is invalid, treat as failure */
15151541
if (c->resp.data != NULL) {
15161542
flb_plg_debug(ctx->ins, "Invalid response: full data: `%.*s`", c->resp.data_len, c->resp.data);

plugins/out_cloudwatch_logs/cloudwatch_logs.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,33 @@ static struct flb_aws_header content_type_header = {
5050
.val_len = 26,
5151
};
5252

53+
static int validate_log_group_class(struct flb_cloudwatch *ctx)
54+
{
55+
if (ctx->create_group == FLB_FALSE) {
56+
flb_plg_error(ctx->ins, "Configuring log_group_class requires `auto_create_group On`.");
57+
return -1;
58+
}
59+
60+
if (ctx->log_group_class == NULL || strlen(ctx->log_group_class) == 0) {
61+
ctx->log_group_class_type = LOG_CLASS_DEFAULT_TYPE;
62+
ctx->log_group_class = LOG_CLASS_STANDARD;
63+
return 0;
64+
} else if (strncmp(ctx->log_group_class, LOG_CLASS_STANDARD, LOG_CLASS_STANDARD_LEN) == 0) {
65+
flb_plg_debug(ctx->ins, "Using explicitly configured `log_group_class %s`, which is the default log class.", ctx->log_group_class);
66+
ctx->log_group_class_type = LOG_CLASS_STANDARD_TYPE;
67+
return 0;
68+
} else if (strncmp(ctx->log_group_class, LOG_CLASS_INFREQUENT_ACCESS, LOG_CLASS_INFREQUENT_ACCESS_LEN) == 0) {
69+
flb_plg_warn(ctx->ins, "Configured `log_group_class %s` will only apply to log groups created by Fluent Bit. "
70+
"Look for the `Created log group` info level message emitted when a group does not already exist and is created.", ctx->log_group_class);
71+
ctx->log_group_class_type = LOG_CLASS_INFREQUENT_ACCESS_TYPE;
72+
return 0;
73+
}
74+
75+
flb_plg_error(ctx->ins, "The valid values for log_group_class are {%s, %s}. Invalid input was %s", LOG_CLASS_STANDARD, LOG_CLASS_INFREQUENT_ACCESS, ctx->log_group_class);
76+
77+
return -1;
78+
}
79+
5380
static int cb_cloudwatch_init(struct flb_output_instance *ins,
5481
struct flb_config *config, void *data)
5582
{
@@ -211,6 +238,11 @@ static int cb_cloudwatch_init(struct flb_output_instance *ins,
211238
ctx->sts_endpoint = (char *) tmp;
212239
}
213240

241+
ret = validate_log_group_class(ctx);
242+
if (ret < 0) {
243+
goto error;
244+
}
245+
214246
/* one tls instance for provider, one for cw client */
215247
ctx->cred_tls = flb_tls_create(FLB_TLS_CLIENT_MODE,
216248
FLB_TRUE,
@@ -652,6 +684,12 @@ static struct flb_config_map config_map[] = {
652684
"$HOME/.aws/ directory."
653685
},
654686

687+
{
688+
FLB_CONFIG_MAP_STR, "log_group_class", "",
689+
0, FLB_TRUE, offsetof(struct flb_cloudwatch, log_group_class),
690+
"Specify the log storage class. Valid values are STANDARD (default) and INFREQUENT_ACCESS."
691+
},
692+
655693
/* EOF */
656694
{0}
657695
};

plugins/out_cloudwatch_logs/cloudwatch_logs.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@
3030
#include <fluent-bit/flb_record_accessor.h>
3131
#include <fluent-bit/record_accessor/flb_ra_parser.h>
3232

33+
#define LOG_CLASS_STANDARD "STANDARD"
34+
#define LOG_CLASS_STANDARD_LEN 8
35+
#define LOG_CLASS_INFREQUENT_ACCESS "INFREQUENT_ACCESS"
36+
#define LOG_CLASS_INFREQUENT_ACCESS_LEN 17
37+
/* log_group_class not configured; do not send the logGroupClass field in request */
38+
#define LOG_CLASS_DEFAULT_TYPE 0
39+
/* send configured & validated string in request */
40+
#define LOG_CLASS_STANDARD_TYPE 1
41+
#define LOG_CLASS_INFREQUENT_ACCESS_TYPE 2
42+
3343
/* buffers used for each flush */
3444
struct cw_flush {
3545
/* temporary buffer for storing the serialized event messages */
@@ -113,6 +123,8 @@ struct flb_cloudwatch {
113123
const char *extra_user_agent;
114124
const char *external_id;
115125
const char *profile;
126+
const char *log_group_class;
127+
int log_group_class_type;
116128
int custom_endpoint;
117129
/* Should the plugin create the log group */
118130
int create_group;

0 commit comments

Comments
 (0)