Skip to content
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

logs_to_metrics: Support optional value_field for counters #10055

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 53 additions & 9 deletions plugins/filter_log_to_metrics/log_to_metrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,13 +639,14 @@ static int cb_log_to_metrics_init(struct flb_filter_instance *f_ins,
snprintf(metric_description, sizeof(metric_description) - 1, "%s",
ctx->metric_description);

/* Value field only needed for modes gauge and histogram */
if (ctx->mode > 0) {
if (ctx->value_field == NULL || strlen(ctx->value_field) == 0) {
flb_plg_error(f_ins, "value_field is not set");
log_to_metrics_destroy(ctx);
return -1;
if (ctx->value_field == NULL || strlen(ctx->value_field) == 0) {
/* require value field for modes gauge and histogram */
if (ctx->mode > 0) {
flb_plg_error(f_ins, "value_field is not set");
log_to_metrics_destroy(ctx);
return -1;
}
} else {
snprintf(value_field, sizeof(value_field) - 1, "%s",
ctx->value_field);
}
Expand Down Expand Up @@ -825,6 +826,7 @@ static int cb_log_to_metrics_filter(const void *data, size_t bytes,
char **label_values = NULL;
int label_count = 0;
int i;
double counter_value = 0;
double gauge_value = 0;
double histogram_value = 0;
char kubernetes_label_values
Expand Down Expand Up @@ -901,8 +903,50 @@ static int cb_log_to_metrics_filter(const void *data, size_t bytes,
/* Calculating and setting metric depending on the mode */
switch (ctx->mode) {
case FLB_LOG_TO_METRICS_COUNTER:
ret = cmt_counter_inc(ctx->c, ts, label_count,
label_values);

// If value_field is not set, increment counter by 1
if (ctx->value_field == NULL || strlen(ctx->value_field) == 0) {
ret = cmt_counter_inc(ctx->c, ts, label_count,
label_values);
break;
}
// If value_field is set, increment counter by value
ra = flb_ra_create(ctx->value_field, FLB_TRUE);
if (!ra) {
flb_plg_error(ctx->ins, "invalid record accessor key, aborting");
break;
}

rval = flb_ra_get_value_object(ra, map);

if (!rval) {
flb_warn("given value field is empty or not existent");
break;
}
if (rval->type == FLB_RA_STRING) {
sscanf(rval->val.string, "%lf", &counter_value);
}
else if (rval->type == FLB_RA_FLOAT) {
counter_value = rval->val.f64;
}
else if (rval->type == FLB_RA_INT) {
counter_value = (double)rval->val.i64;
}
else {
flb_plg_error(f_ins,
"cannot convert given value to metric");
break;
}
ret = cmt_counter_add(ctx->c, ts, counter_value,
label_count, label_values);
if (rval) {
flb_ra_key_value_destroy(rval);
rval = NULL;
}
if (ra) {
flb_ra_destroy(ra);
ra = NULL;
}
break;

case FLB_LOG_TO_METRICS_GAUGE:
Expand Down Expand Up @@ -1066,7 +1110,7 @@ static struct flb_config_map config_map[] = {
{
FLB_CONFIG_MAP_STR, "value_field", NULL,
0, FLB_TRUE, offsetof(struct log_to_metrics_ctx, value_field),
"Numeric field to use for gauge or histogram"
"Numeric field to use for gauge, histogram or counter"
},
{
FLB_CONFIG_MAP_STR, "metric_name", "a",
Expand Down
70 changes: 70 additions & 0 deletions tests/runtime/filter_log_to_metrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
/* Test functions */
void flb_test_log_to_metrics_counter_k8s(void);
void flb_test_log_to_metrics_counter(void);
void flb_test_log_to_metrics_counter_value_field(void);
void flb_test_log_to_metrics_counter_k8s_two_tuples(void);
void flb_test_log_to_metrics_gauge(void);
void flb_test_log_to_metrics_histogram(void);
Expand Down Expand Up @@ -118,6 +119,7 @@ void flb_test_log_to_metrics_label(void);
TEST_LIST = {
{"counter_k8s", flb_test_log_to_metrics_counter_k8s },
{"counter", flb_test_log_to_metrics_counter },
{"counter_value_field", flb_test_log_to_metrics_counter_value_field },
{"counter_k8s_two_tuples", flb_test_log_to_metrics_counter_k8s_two_tuples },
{"gauge", flb_test_log_to_metrics_gauge },
{"histogram", flb_test_log_to_metrics_histogram },
Expand Down Expand Up @@ -321,6 +323,74 @@ void flb_test_log_to_metrics_counter(void)

}

void flb_test_log_to_metrics_counter_value_field(void)
{
int ret;
int i;
flb_ctx_t *ctx;
int in_ffd;
int filter_ffd;
int out_ffd;
char *result = NULL;
struct flb_lib_out_cb cb_data;
char *input = JSON_MSG1;
char finalString[32768] = "";
const char *expected = "\"value\":100.0,\"labels\":[\"red\",\"right\"]";
const char *expected2 = "{\"ns\":\"myns\",\"ss\":\"subsystem\","
"\"name\":\"test\",\"desc\":\"Counts durations\"}";

ctx = flb_create();
flb_service_set(ctx, "Flush", "0.200000000", "Grace", "1", "Log_Level",
"error", NULL);

cb_data.cb = callback_test;
cb_data.data = NULL;

in_ffd = flb_input(ctx, (char *) "lib", NULL);
TEST_CHECK(in_ffd >= 0);
flb_input_set(ctx, in_ffd, "tag", "test", NULL);

filter_ffd = flb_filter(ctx, (char *) "log_to_metrics", NULL);
TEST_CHECK(filter_ffd >= 0);
ret = flb_filter_set(ctx, filter_ffd,
"Match", "*",
"Tag", "test_metric",
"metric_mode", "counter",
"metric_name", "test",
"metric_description", "Counts durations",
"metric_subsystem", "subsystem",
"metric_namespace", "myns",
"kubernetes_mode", "off",
"label_field", "color",
"label_field", "direction",
"value_field", "duration",
NULL);

out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data);
TEST_CHECK(out_ffd >= 0);
flb_output_set(ctx, out_ffd,
"match", "*",
"format", "json",
NULL);
ret = flb_start(ctx);
TEST_CHECK(ret == 0);

for (i = 0; i < 5; i++){
flb_lib_push(ctx, in_ffd, input, strlen(input));
}
wait_with_timeout(2000, finalString);
result = strstr(finalString, expected);
if (!TEST_CHECK(result != NULL)) {
TEST_MSG("expected substring:\n%s\ngot:\n%s\n", expected, finalString);
}
result = strstr(finalString, expected2);
if (!TEST_CHECK(result != NULL)) {
TEST_MSG("expected substring:\n%s\ngot:\n%s\n", expected, finalString);
}
filter_test_destroy(ctx);

}

void flb_test_log_to_metrics_counter_k8s_two_tuples(void)
{
int ret;
Expand Down