From c2d9228ba0f8c8a04c4e9c94dcb229f01efc8fbf Mon Sep 17 00:00:00 2001 From: Takahiro Yamashita Date: Sat, 28 Oct 2023 16:49:56 +0900 Subject: [PATCH] filter_sysinfo: add filter sysinfo plugin Signed-off-by: Takahiro Yamashita --- CMakeLists.txt | 1 + plugins/CMakeLists.txt | 1 + plugins/filter_sysinfo/CMakeLists.txt | 5 + plugins/filter_sysinfo/sysinfo.c | 282 +++++++++++++++++ plugins/filter_sysinfo/sysinfo.h | 51 ++++ plugins/filter_sysinfo/sysinfo_platform.c | 115 +++++++ .../filter_sysinfo/sysinfo_platform_linux.c | 76 +++++ tests/runtime/CMakeLists.txt | 1 + tests/runtime/filter_sysinfo.c | 287 ++++++++++++++++++ 9 files changed, 819 insertions(+) create mode 100644 plugins/filter_sysinfo/CMakeLists.txt create mode 100644 plugins/filter_sysinfo/sysinfo.c create mode 100644 plugins/filter_sysinfo/sysinfo.h create mode 100644 plugins/filter_sysinfo/sysinfo_platform.c create mode 100644 plugins/filter_sysinfo/sysinfo_platform_linux.c create mode 100644 tests/runtime/filter_sysinfo.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 99109309405..0facf2917d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,6 +265,7 @@ option(FLB_FILTER_EXPECT "Enable expect filter" option(FLB_FILTER_GREP "Enable grep filter" Yes) option(FLB_FILTER_MODIFY "Enable modify filter" Yes) option(FLB_FILTER_STDOUT "Enable stdout filter" Yes) +option(FLB_FILTER_SYSINFO "Enable sysinfo filter" Yes) option(FLB_FILTER_PARSER "Enable parser filter" Yes) option(FLB_FILTER_KUBERNETES "Enable kubernetes filter" Yes) option(FLB_FILTER_REWRITE_TAG "Enable tag rewrite filter" Yes) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4548cb24f89..df100ea3b73 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -345,6 +345,7 @@ REGISTER_FILTER_PLUGIN("filter_aws") REGISTER_FILTER_PLUGIN("filter_checklist") REGISTER_FILTER_PLUGIN("filter_ecs") REGISTER_FILTER_PLUGIN("filter_record_modifier") +REGISTER_FILTER_PLUGIN("filter_sysinfo") REGISTER_FILTER_PLUGIN("filter_throttle") REGISTER_FILTER_PLUGIN("filter_throttle_size") REGISTER_FILTER_PLUGIN("filter_tensorflow") diff --git a/plugins/filter_sysinfo/CMakeLists.txt b/plugins/filter_sysinfo/CMakeLists.txt new file mode 100644 index 00000000000..7d55fc245c2 --- /dev/null +++ b/plugins/filter_sysinfo/CMakeLists.txt @@ -0,0 +1,5 @@ +set(src + sysinfo.c + sysinfo_platform.c) + +FLB_PLUGIN(filter_sysinfo "${src}" "") diff --git a/plugins/filter_sysinfo/sysinfo.c b/plugins/filter_sysinfo/sysinfo.c new file mode 100644 index 00000000000..348018a467f --- /dev/null +++ b/plugins/filter_sysinfo/sysinfo.c @@ -0,0 +1,282 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 The Fluent Bit Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include "sysinfo.h" + +static int cb_sysinfo_init(struct flb_filter_instance *f_ins, + struct flb_config *config, + void *data) +{ + struct filter_sysinfo_ctx *ctx = NULL; + int ret; + (void) config; + (void) data; + + ctx = flb_calloc(1, sizeof(struct filter_sysinfo_ctx)); + if (ctx == NULL) { + flb_errno(); + return -1; + } + ctx->ins = f_ins; + + if (flb_filter_config_map_set(f_ins, ctx) == -1) { + flb_plg_error(f_ins, "unable to load configuration"); + flb_free(ctx); + return -1; + } + + ret = flb_sysinfo_platform_init(ctx); + if (ret != 0) { + flb_free(ctx); + return -1; + } + + flb_filter_set_context(f_ins, ctx); + + return 0; +} + +static int init_encoder_decoder(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc, + struct flb_log_event_decoder *dec, + char *data, size_t bytes) +{ + int dec_ret; + int enc_ret; + + dec_ret = flb_log_event_decoder_init(dec, (char *) data, bytes); + if (dec_ret != FLB_EVENT_DECODER_SUCCESS) { + flb_plg_error(ctx->ins, + "Log event decoder initialization error : %s", + flb_log_event_decoder_get_error_description(dec_ret)); + + return -1; + } + enc_ret = flb_log_event_encoder_init(enc, FLB_LOG_EVENT_FORMAT_DEFAULT); + if (enc_ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_plg_error(ctx->ins, + "Log event encoder initialization error : %s", + flb_log_event_encoder_get_error_description(enc_ret)); + flb_log_event_decoder_destroy(dec); + return -1; + } + return 0; +} + +static int exit_encoder_decoder(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc, + struct flb_log_event_decoder *dec, + void **out_buf, size_t *out_bytes) +{ + int dec_ret; + int ret = FLB_FILTER_NOTOUCH; + + dec_ret = flb_log_event_decoder_get_last_result(dec); + if (dec_ret == FLB_EVENT_DECODER_SUCCESS) { + if (enc->output_length > 0) { + *out_buf = enc->output_buffer; + *out_bytes = enc->output_length; + ret = FLB_FILTER_MODIFIED; + flb_log_event_encoder_claim_internal_buffer_ownership(enc); + } + } + else { + flb_plg_error(ctx->ins, + "flb_log_event_decoder_get_last_result error : %s", + flb_log_event_decoder_get_error_description(dec_ret)); + } + + flb_log_event_decoder_destroy(dec); + flb_log_event_encoder_destroy(enc); + + return ret; +} + + + +static int copy_original_event(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc, + struct flb_log_event *log_event) +{ + msgpack_object *obj; + int enc_ret; + int map_num; + int i; + + + enc_ret = flb_log_event_encoder_begin_record(enc); + if (enc_ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_plg_error(ctx->ins, "flb_log_event_encoder_begin_record failed: %s", + flb_log_event_encoder_get_error_description(enc_ret)); + return -1; + } + + enc_ret = flb_log_event_encoder_set_timestamp(enc, &log_event->timestamp); + if (enc_ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_plg_error(ctx->ins, "flb_log_event_encoder_set_timestamp failed: %s", + flb_log_event_encoder_get_error_description(enc_ret)); + return -1; + } + + obj = log_event->body; + if (obj->type != MSGPACK_OBJECT_MAP) { + flb_plg_error(ctx->ins, "body object is not a map"); + return -1; + } + + map_num = obj->via.map.size; + + for (i=0; ivia.map.ptr[i].key), + FLB_LOG_EVENT_MSGPACK_OBJECT_VALUE(&obj->via.map.ptr[i].val)); + if (enc_ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_plg_error(ctx->ins, "flb_log_event_encoder_append_body_values failed: %s", + flb_log_event_encoder_get_error_description(enc_ret)); + return -1; + } + } + + enc_ret = flb_log_event_encoder_set_metadata_from_msgpack_object(enc, + log_event->metadata); + if (enc_ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_plg_error(ctx->ins, "flb_log_event_encoder_set_metadata_from_msgpack_object failed: %s", + flb_log_event_encoder_get_error_description(enc_ret)); + return -1; + } + + + return 0; +} + +static int cb_sysinfo_filter(const void *data, size_t bytes, + const char *tag, int tag_len, + void **out_buf, size_t *out_bytes, + struct flb_filter_instance *f_ins, + struct flb_input_instance *i_ins, + void *filter_context, + struct flb_config *config) +{ + struct filter_sysinfo_ctx *ctx = filter_context; + struct flb_log_event_decoder log_decoder; + struct flb_log_event_encoder log_encoder; + struct flb_log_event log_event; + int dec_ret; + int ret; + + (void) f_ins; + (void) i_ins; + (void) filter_context; + (void) config; + + ret = init_encoder_decoder(ctx, &log_encoder, &log_decoder, (char*)data, bytes); + if (ret != 0) { + return FLB_FILTER_NOTOUCH; + } + + while ((dec_ret = flb_log_event_decoder_next( + &log_decoder, + &log_event)) == FLB_EVENT_DECODER_SUCCESS) { + ret = copy_original_event(ctx, &log_encoder, &log_event); + if (ret != 0) { + flb_log_event_encoder_rollback_record(&log_encoder); + continue; + } + + ret = flb_sysinfo_append_common_info(ctx, &log_encoder); + if (ret != 0) { + flb_log_event_encoder_rollback_record(&log_encoder); + continue; + } + ret = flb_sysinfo_platform_filter(ctx, &log_encoder, &log_decoder); + if (ret != 0) { + flb_log_event_encoder_rollback_record(&log_encoder); + continue; + } + + flb_log_event_encoder_commit_record(&log_encoder); + } + + return exit_encoder_decoder(ctx, &log_encoder, &log_decoder, out_buf, out_bytes); +} + +static int cb_sysinfo_exit(void *data, struct flb_config *config) +{ + struct filter_sysinfo_ctx *ctx = data; + if (ctx == NULL) { + return 0; + } + flb_sysinfo_platform_exit(ctx); + + flb_free(ctx); + + return 0; +} + +static struct flb_config_map config_map[] = { + { + FLB_CONFIG_MAP_STR, "fluentbit_version_key", NULL, + 0, FLB_TRUE, offsetof(struct filter_sysinfo_ctx, flb_ver_key), + "Specify the key name for fluent-bit version." + }, + { + FLB_CONFIG_MAP_STR, "os_name_key", NULL, + 0, FLB_TRUE, offsetof(struct filter_sysinfo_ctx, os_name_key), + "Specify the key name for os name. e.g. linux, win64 or macos." + }, + { + FLB_CONFIG_MAP_STR, "hostname_key", NULL, + 0, FLB_TRUE, offsetof(struct filter_sysinfo_ctx, hostname_key), + "Specify the key name for hostname." + }, + + + + /* Platform specific config */ + { + FLB_CONFIG_MAP_STR, "os_version_key", NULL, + 0, FLB_TRUE, offsetof(struct filter_sysinfo_ctx, os_version_key), + "Specify the key name for os version. It is not supported on some platforms." + }, + { + FLB_CONFIG_MAP_STR, "kernel_version_key", NULL, + 0, FLB_TRUE, offsetof(struct filter_sysinfo_ctx, kernel_version_key), + "Specify the key name for kernel version. It is not supported on some platforms." + }, + + /* EOF */ + {0} +}; + +struct flb_filter_plugin filter_sysinfo_plugin = { + .name = "sysinfo", + .description = "Filter for system info", + .cb_init = cb_sysinfo_init, + .cb_filter = cb_sysinfo_filter, + .cb_exit = cb_sysinfo_exit, + .config_map = config_map, + .flags = 0 +}; diff --git a/plugins/filter_sysinfo/sysinfo.h b/plugins/filter_sysinfo/sysinfo.h new file mode 100644 index 00000000000..0f844a4a705 --- /dev/null +++ b/plugins/filter_sysinfo/sysinfo.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 The Fluent Bit Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLB_FILTER_SYSINFO_H +#define FLB_FILTER_SYSINFO_H + +#include +#include +#include +#include + +struct filter_sysinfo_ctx { + struct flb_filter_instance *ins; + + flb_sds_t flb_ver_key; + flb_sds_t os_name_key; + flb_sds_t hostname_key; + + /* Platform specific */ + flb_sds_t os_version_key; + flb_sds_t kernel_version_key; +}; + +int flb_sysinfo_append_common_info(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc); + + +/* Platform specific API */ +int flb_sysinfo_platform_init(struct filter_sysinfo_ctx *ctx); +int flb_sysinfo_platform_filter(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc, + struct flb_log_event_decoder *dec); +int flb_sysinfo_platform_exit(struct filter_sysinfo_ctx *ctx); + +#endif diff --git a/plugins/filter_sysinfo/sysinfo_platform.c b/plugins/filter_sysinfo/sysinfo_platform.c new file mode 100644 index 00000000000..808bc4550c5 --- /dev/null +++ b/plugins/filter_sysinfo/sysinfo_platform.c @@ -0,0 +1,115 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 The Fluent Bit Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sysinfo.h" +#include +#include +#include +#include + +static int append_key_value_str(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc, + char *key, char *val) +{ + /* TODO: add kv to metadata ? */ + + return flb_log_event_encoder_append_body_values(enc, + FLB_LOG_EVENT_CSTRING_VALUE(key), + FLB_LOG_EVENT_CSTRING_VALUE(val)); +} + +static int sysinfo_append_flb_ver(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc) +{ + return append_key_value_str(ctx, enc, ctx->flb_ver_key, FLB_VERSION_STR); +} + +static int sysinfo_append_os_name(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc) +{ + return append_key_value_str(ctx, enc, ctx->os_name_key, flb_utils_get_os_name()); +} + +static int sysinfo_append_hostname(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc) +{ + int ret; + char hostname[1024]; + + ret = gethostname(&hostname[0], sizeof(hostname)-1); + if (ret < 0) { + return append_key_value_str(ctx, enc, ctx->hostname_key, "unknown"); + } + hostname[sizeof(hostname)-1] = '\0'; + return append_key_value_str(ctx, enc, ctx->hostname_key, &hostname[0]); +} + +int flb_sysinfo_append_common_info(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc) +{ + if (ctx->flb_ver_key) { + sysinfo_append_flb_ver(ctx, enc); + } + if (ctx->os_name_key) { + sysinfo_append_os_name(ctx, enc); + } + if (ctx->hostname_key) { + sysinfo_append_hostname(ctx, enc); + } + + return 0; +} + + + + +/* Platform specific code */ +#ifdef __linux__ +#include "sysinfo_platform_linux.c" +#else + +#include + +int flb_sysinfo_platform_init(struct filter_sysinfo_ctx *ctx) +{ + if (ctx->os_version_key) { + flb_plg_warn(ctx->ins, "%s is ignored since this platform doesn't support", + ctx->os_version_key); + } + if (ctx->kernel_version_key) { + flb_plg_warn(ctx->ins, "%s is ignored since this platform doesn't support", + ctx->kernel_version_key); + } + + return 0; +} + +int flb_sysinfo_platform_filter(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc, + struct flb_log_event_decoder *dec) +{ + return 0; +} + + +int flb_sysinfo_platform_exit(struct filter_sysinfo_ctx *ctx) +{ + return 0; +} +#endif diff --git a/plugins/filter_sysinfo/sysinfo_platform_linux.c b/plugins/filter_sysinfo/sysinfo_platform_linux.c new file mode 100644 index 00000000000..170eeee58fb --- /dev/null +++ b/plugins/filter_sysinfo/sysinfo_platform_linux.c @@ -0,0 +1,76 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 The Fluent Bit Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sysinfo.h" +#include +#include + +static int sysinfo_append_os_version(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc) +{ + struct utsname uts; + int ret; + + ret = uname(&uts); + if (ret < 0) { + return append_key_value_str(ctx, enc, ctx->os_version_key, "unknown"); + } + + return append_key_value_str(ctx, enc, ctx->os_version_key, uts.version); +} + +static int sysinfo_append_kernel_version(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc) +{ + struct utsname uts; + int ret; + + ret = uname(&uts); + if (ret < 0) { + return append_key_value_str(ctx, enc, ctx->kernel_version_key, "unknown"); + } + + return append_key_value_str(ctx, enc, ctx->kernel_version_key, uts.release); +} + + +int flb_sysinfo_platform_init(struct filter_sysinfo_ctx *ctx) +{ + return 0; +} + +int flb_sysinfo_platform_filter(struct filter_sysinfo_ctx *ctx, + struct flb_log_event_encoder *enc, + struct flb_log_event_decoder *dec) +{ + if (ctx->os_version_key) { + sysinfo_append_os_version(ctx, enc); + } + if (ctx->kernel_version_key) { + sysinfo_append_kernel_version(ctx, enc); + } + + return 0; +} + + +int flb_sysinfo_platform_exit(struct filter_sysinfo_ctx *ctx) +{ + return 0; +} diff --git a/tests/runtime/CMakeLists.txt b/tests/runtime/CMakeLists.txt index d6d3e710153..74330fe62dc 100644 --- a/tests/runtime/CMakeLists.txt +++ b/tests/runtime/CMakeLists.txt @@ -76,6 +76,7 @@ if(FLB_IN_LIB AND FLB_OUT_LIB) FLB_RT_TEST(FLB_FILTER_TYPE_CONVERTER "filter_type_converter.c") FLB_RT_TEST(FLB_FILTER_RECORD_MODIFIER "filter_record_modifier.c") FLB_RT_TEST(FLB_FILTER_MULTILINE "filter_multiline.c") + FLB_RT_TEST(FLB_FILTER_SYSINFO "filter_sysinfo.c") if (FLB_FILTER_WASM) FLB_RT_TEST(FLB_FILTER_WASM "filter_wasm.c") endif () diff --git a/tests/runtime/filter_sysinfo.c b/tests/runtime/filter_sysinfo.c new file mode 100644 index 00000000000..d0157ac6fbf --- /dev/null +++ b/tests/runtime/filter_sysinfo.c @@ -0,0 +1,287 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2019-2023 The Fluent Bit Authors + * Copyright (C) 2015-2018 Treasure Data Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "flb_tests_runtime.h" +#include "data/common/json_long.h" /* JSON_LONG */ + +struct filter_test { + flb_ctx_t *flb; /* Fluent Bit library context */ + int i_ffd; /* Input fd */ + int f_ffd; /* Filter fd */ + int o_ffd; /* Output fd */ +}; + +struct expect_str { + char *str; + int found; +}; + + +/* Callback to check expected results */ +static int cb_check_result(void *record, size_t size, void *data) +{ + char *p; + char *result; + struct expect_str *expected; + + expected = (struct expect_str*)data; + result = (char *) record; + + if (!TEST_CHECK(expected != NULL)) { + flb_error("expected is NULL"); + } + if (!TEST_CHECK(result != NULL)) { + flb_error("result is NULL"); + } + + while(expected != NULL && expected->str != NULL) { + if (expected->found == FLB_TRUE) { + p = strstr(result, expected->str); + if(!TEST_CHECK(p != NULL)) { + flb_error("Expected to find: '%s' in result '%s'", + expected->str, result); + } + } + else { + p = strstr(result, expected->str); + if(!TEST_CHECK(p == NULL)) { + flb_error("'%s' should be removed in result '%s'", + expected->str, result); + } + } + + /* + * If you want to debug your test + * + * printf("Expect: '%s' in result '%s'", expected, result); + */ + + expected++; + } + + flb_free(record); + return 0; +} + +static struct filter_test *filter_test_create(struct flb_lib_out_cb *data) +{ + int i_ffd; + int f_ffd; + int o_ffd; + struct filter_test *ctx; + + ctx = flb_malloc(sizeof(struct filter_test)); + if (!ctx) { + flb_errno(); + return NULL; + } + + /* Service config */ + ctx->flb = flb_create(); + flb_service_set(ctx->flb, + "Flush", "0.200000000", + "Grace", "1", + "Log_Level", "error", + NULL); + + /* Input */ + i_ffd = flb_input(ctx->flb, (char *) "lib", NULL); + TEST_CHECK(i_ffd >= 0); + flb_input_set(ctx->flb, i_ffd, "tag", "test", NULL); + ctx->i_ffd = i_ffd; + + /* Filter configuration */ + f_ffd = flb_filter(ctx->flb, (char *) "sysinfo", NULL); + TEST_CHECK(f_ffd >= 0); + flb_filter_set(ctx->flb, f_ffd, "match", "*", NULL); + ctx->f_ffd = f_ffd; + + /* Output */ + o_ffd = flb_output(ctx->flb, (char *) "lib", (void *) data); + TEST_CHECK(o_ffd >= 0); + flb_output_set(ctx->flb, o_ffd, + "match", "test", + NULL); + ctx->o_ffd = o_ffd; + + return ctx; +} + +static void filter_test_destroy(struct filter_test *ctx) +{ + sleep(1); + flb_stop(ctx->flb); + flb_destroy(ctx->flb); + flb_free(ctx); +} + +static void flb_ver_key() +{ + int len; + int ret; + int bytes; + char *p; + struct flb_lib_out_cb cb_data; + struct filter_test *ctx; + struct expect_str expect[] = { + {"\"flb_ver\"", FLB_TRUE}, + {FLB_VERSION_STR, FLB_TRUE}, + {"\"k\":\"sample\"", FLB_TRUE}, + {NULL, FLB_TRUE} + }; + + /* Create test context */ + ctx = filter_test_create((void *) &cb_data); + if (!ctx) { + exit(EXIT_FAILURE); + } + + /* Configure filter */ + ret = flb_filter_set(ctx->flb, ctx->f_ffd, + "fluentbit_version_key", "flb_ver", + NULL); + TEST_CHECK(ret == 0); + + ret = flb_output_set(ctx->flb, ctx->o_ffd, + "format", "json", + NULL); + TEST_CHECK(ret == 0); + + /* Prepare output callback with expected result */ + cb_data.cb = cb_check_result; + cb_data.data = &expect; + + /* Start the engine */ + ret = flb_start(ctx->flb); + TEST_CHECK(ret == 0); + + /* Ingest data samples */ + p = "[0, {\"k\":\"sample\"}]"; + len = strlen(p); + bytes = flb_lib_push(ctx->flb, ctx->i_ffd, p, len); + TEST_CHECK(bytes == len); + + filter_test_destroy(ctx); +} + +static void hostname_key() +{ + int len; + int ret; + int bytes; + char *p; + struct flb_lib_out_cb cb_data; + struct filter_test *ctx; + struct expect_str expect[] = { + {"\"h_key\"", FLB_TRUE}, + {NULL, FLB_TRUE} + }; + + /* Create test context */ + ctx = filter_test_create((void *) &cb_data); + if (!ctx) { + exit(EXIT_FAILURE); + } + + /* Configure filter */ + ret = flb_filter_set(ctx->flb, ctx->f_ffd, + "hostname_key", "h_key", + NULL); + TEST_CHECK(ret == 0); + + ret = flb_output_set(ctx->flb, ctx->o_ffd, + "format", "json", + NULL); + TEST_CHECK(ret == 0); + + /* Prepare output callback with expected result */ + cb_data.cb = cb_check_result; + cb_data.data = &expect; + + /* Start the engine */ + ret = flb_start(ctx->flb); + TEST_CHECK(ret == 0); + + /* Ingest data samples */ + p = "[0, {\"k\":\"sample\"}]"; + len = strlen(p); + bytes = flb_lib_push(ctx->flb, ctx->i_ffd, p, len); + TEST_CHECK(bytes == len); + + filter_test_destroy(ctx); +} + +static void os_name_key() +{ + int len; + int ret; + int bytes; + char *p; + struct flb_lib_out_cb cb_data; + struct filter_test *ctx; + struct expect_str expect[] = { + {"\"os_key\"", FLB_TRUE}, + {NULL, FLB_TRUE} + }; + + /* Create test context */ + ctx = filter_test_create((void *) &cb_data); + if (!ctx) { + exit(EXIT_FAILURE); + } + + /* Configure filter */ + ret = flb_filter_set(ctx->flb, ctx->f_ffd, + "os_name_key", "os_key", + NULL); + TEST_CHECK(ret == 0); + + ret = flb_output_set(ctx->flb, ctx->o_ffd, + "format", "json", + NULL); + TEST_CHECK(ret == 0); + + /* Prepare output callback with expected result */ + cb_data.cb = cb_check_result; + cb_data.data = &expect; + + /* Start the engine */ + ret = flb_start(ctx->flb); + TEST_CHECK(ret == 0); + + /* Ingest data samples */ + p = "[0, {\"k\":\"sample\"}]"; + len = strlen(p); + bytes = flb_lib_push(ctx->flb, ctx->i_ffd, p, len); + TEST_CHECK(bytes == len); + + filter_test_destroy(ctx); +} + +/* test list */ +TEST_LIST = { + {"fluentbit_version_key" , flb_ver_key }, + {"hostname_key" , hostname_key }, + {"os_name_key" , os_name_key }, + {NULL, NULL} +};