summaryrefslogtreecommitdiffstats
path: root/fluent-bit/src/flb_custom.c
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/src/flb_custom.c')
-rw-r--r--fluent-bit/src/flb_custom.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/fluent-bit/src/flb_custom.c b/fluent-bit/src/flb_custom.c
new file mode 100644
index 000000000..8279bb65d
--- /dev/null
+++ b/fluent-bit/src/flb_custom.c
@@ -0,0 +1,314 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2022 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 <fluent-bit/flb_config.h>
+#include <fluent-bit/flb_custom.h>
+#include <fluent-bit/flb_str.h>
+#include <fluent-bit/flb_env.h>
+#include <fluent-bit/flb_router.h>
+#include <fluent-bit/flb_mp.h>
+#include <fluent-bit/flb_kv.h>
+#include <fluent-bit/flb_pack.h>
+#include <fluent-bit/flb_metrics.h>
+#include <fluent-bit/flb_utils.h>
+#include <chunkio/chunkio.h>
+
+static inline int instance_id(struct flb_config *config)
+{
+ struct flb_custom_instance *entry;
+
+ if (mk_list_size(&config->customs) == 0) {
+ return 0;
+ }
+
+ entry = mk_list_entry_last(&config->customs, struct flb_custom_instance,
+ _head);
+ return (entry->id + 1);
+}
+
+static inline int prop_key_check(const char *key, const char *kv, int k_len)
+{
+ int len;
+
+ len = strlen(key);
+ if (strncasecmp(key, kv, k_len) == 0 && len == k_len) {
+ return 0;
+ }
+
+ return -1;
+}
+
+int flb_custom_set_property(struct flb_custom_instance *ins,
+ const char *k, const char *v)
+{
+ int len;
+ int ret;
+ flb_sds_t tmp;
+ struct flb_kv *kv;
+
+ len = strlen(k);
+ tmp = flb_env_var_translate(ins->config->env, v);
+ if (!tmp) {
+ return -1;
+ }
+
+ if (prop_key_check("alias", k, len) == 0 && tmp) {
+ flb_utils_set_plugin_string_property("alias", &ins->alias, tmp);
+ }
+ else if (prop_key_check("log_level", k, len) == 0 && tmp) {
+ ret = flb_log_get_level_str(tmp);
+ flb_sds_destroy(tmp);
+ if (ret == -1) {
+ return -1;
+ }
+ ins->log_level = ret;
+ }
+ else {
+ /*
+ * Create the property, we don't pass the value since we will
+ * map it directly to avoid an extra memory allocation.
+ */
+ kv = flb_kv_item_create(&ins->properties, (char *) k, NULL);
+ if (!kv) {
+ if (tmp) {
+ flb_sds_destroy(tmp);
+ }
+ return -1;
+ }
+ kv->val = tmp;
+ }
+
+ return 0;
+}
+
+const char *flb_custom_get_property(const char *key,
+ struct flb_custom_instance *ins)
+{
+ return flb_kv_get_key_value(key, &ins->properties);
+}
+
+void flb_custom_instance_exit(struct flb_custom_instance *ins,
+ struct flb_config *config)
+{
+ struct flb_custom_plugin *p;
+
+ p = ins->p;
+ if (p->cb_exit && ins->context) {
+ p->cb_exit(ins->context, config);
+ }
+}
+
+/* Invoke exit call for the custom plugin */
+void flb_custom_exit(struct flb_config *config)
+{
+ struct mk_list *tmp;
+ struct mk_list *head;
+ struct flb_custom_instance *ins;
+ struct flb_custom_plugin *p;
+
+ mk_list_foreach_safe(head, tmp, &config->customs) {
+ ins = mk_list_entry(head, struct flb_custom_instance, _head);
+ p = ins->p;
+ if (!p) {
+ continue;
+ }
+ flb_custom_instance_exit(ins, config);
+ flb_custom_instance_destroy(ins);
+ }
+}
+
+struct flb_custom_instance *flb_custom_new(struct flb_config *config,
+ const char *custom, void *data)
+{
+ int id;
+ struct mk_list *head;
+ struct flb_custom_plugin *plugin;
+ struct flb_custom_instance *instance = NULL;
+
+ if (!custom) {
+ return NULL;
+ }
+
+ mk_list_foreach(head, &config->custom_plugins) {
+ plugin = mk_list_entry(head, struct flb_custom_plugin, _head);
+ if (strcmp(plugin->name, custom) == 0) {
+ break;
+ }
+ plugin = NULL;
+ }
+
+ if (!plugin) {
+ return NULL;
+ }
+
+ instance = flb_calloc(1, sizeof(struct flb_custom_instance));
+ if (!instance) {
+ flb_errno();
+ return NULL;
+ }
+ instance->config = config;
+
+ /* Get an ID */
+ id = instance_id(config);
+
+ /* format name (with instance id) */
+ snprintf(instance->name, sizeof(instance->name) - 1,
+ "%s.%i", plugin->name, id);
+
+ instance->id = id;
+ instance->alias = NULL;
+ instance->p = plugin;
+ instance->data = data;
+ instance->log_level = -1;
+
+ mk_list_init(&instance->properties);
+ mk_list_add(&instance->_head, &config->customs);
+
+ return instance;
+}
+
+/* Return an instance name or alias */
+const char *flb_custom_name(struct flb_custom_instance *ins)
+{
+ if (ins->alias) {
+ return ins->alias;
+ }
+
+ return ins->name;
+}
+
+int flb_custom_plugin_property_check(struct flb_custom_instance *ins,
+ struct flb_config *config)
+{
+ int ret = 0;
+ struct mk_list *config_map;
+ struct flb_custom_plugin *p = ins->p;
+
+ if (p->config_map) {
+ /*
+ * Create a dynamic version of the configmap that will be used by the specific
+ * instance in question.
+ */
+ config_map = flb_config_map_create(config, p->config_map);
+ if (!config_map) {
+ flb_error("[custom] error loading config map for '%s' plugin",
+ p->name);
+ return -1;
+ }
+ ins->config_map = config_map;
+
+ /* Validate incoming properties against config map */
+ ret = flb_config_map_properties_check(ins->p->name,
+ &ins->properties, ins->config_map);
+ if (ret == -1) {
+ if (config->program_name) {
+ flb_helper("try the command: %s -F %s -h\n",
+ config->program_name, ins->p->name);
+ }
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Initialize all custom plugins */
+int flb_custom_init_all(struct flb_config *config)
+{
+ int ret;
+ struct mk_list *tmp;
+ struct mk_list *head;
+ struct flb_custom_plugin *p;
+ struct flb_custom_instance *ins;
+
+ /* Iterate all active custom instance plugins */
+ mk_list_foreach_safe(head, tmp, &config->customs) {
+ ins = mk_list_entry(head, struct flb_custom_instance, _head);
+
+ if (ins->log_level == -1) {
+ ins->log_level = config->log->level;
+ }
+
+ p = ins->p;
+
+#ifdef FLB_HAVE_METRICS
+ /* CMetrics */
+ ins->cmt = cmt_create();
+ if (!ins->cmt) {
+ flb_error("[custom] could not create cmetrics context: %s",
+ flb_custom_name(ins));
+ return -1;
+ }
+#endif
+
+ /*
+ * Before to call the initialization callback, make sure that the received
+ * configuration parameters are valid if the plugin is registering a config map.
+ */
+ if (flb_custom_plugin_property_check(ins, config) == -1) {
+ flb_custom_instance_destroy(ins);
+ return -1;
+ }
+
+ /* Initialize the input */
+ if (p->cb_init) {
+ ret = p->cb_init(ins, config, ins->data);
+ if (ret != 0) {
+ flb_error("Failed initialize custom %s", ins->name);
+ flb_custom_instance_destroy(ins);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void flb_custom_instance_destroy(struct flb_custom_instance *ins)
+{
+ if (!ins) {
+ return;
+ }
+
+ /* destroy config map */
+ if (ins->config_map) {
+ flb_config_map_destroy(ins->config_map);
+ }
+
+ /* release properties */
+ flb_kv_release(&ins->properties);
+
+ if (ins->alias) {
+ flb_sds_destroy(ins->alias);
+ }
+
+#ifdef FLB_HAVE_METRICS
+ if (ins->cmt) {
+ cmt_destroy(ins->cmt);
+ }
+#endif
+
+ mk_list_del(&ins->_head);
+ flb_free(ins);
+}
+
+void flb_custom_set_context(struct flb_custom_instance *ins, void *context)
+{
+ ins->context = context;
+}