Coverage Report

Created: 2023-01-10 06:17

/src/fluent-bit/src/flb_custom.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2022 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#include <fluent-bit/flb_config.h>
21
#include <fluent-bit/flb_custom.h>
22
#include <fluent-bit/flb_str.h>
23
#include <fluent-bit/flb_env.h>
24
#include <fluent-bit/flb_router.h>
25
#include <fluent-bit/flb_mp.h>
26
#include <fluent-bit/flb_kv.h>
27
#include <fluent-bit/flb_pack.h>
28
#include <fluent-bit/flb_metrics.h>
29
#include <chunkio/chunkio.h>
30
31
static inline int instance_id(struct flb_config *config)
32
0
{
33
0
    struct flb_custom_instance *entry;
34
35
0
    if (mk_list_size(&config->customs) == 0) {
36
0
        return 0;
37
0
    }
38
39
0
    entry = mk_list_entry_last(&config->customs, struct flb_custom_instance,
40
0
                               _head);
41
0
    return (entry->id + 1);
42
0
}
43
44
static inline int prop_key_check(const char *key, const char *kv, int k_len)
45
0
{
46
0
    int len;
47
48
0
    len = strlen(key);
49
0
    if (strncasecmp(key, kv, k_len) == 0 && len == k_len) {
50
0
        return 0;
51
0
    }
52
53
0
    return -1;
54
0
}
55
56
int flb_custom_set_property(struct flb_custom_instance *ins,
57
                            const char *k, const char *v)
58
0
{
59
0
    int len;
60
0
    int ret;
61
0
    flb_sds_t tmp;
62
0
    struct flb_kv *kv;
63
64
0
    len = strlen(k);
65
0
    tmp = flb_env_var_translate(ins->config->env, v);
66
0
    if (!tmp) {
67
0
        return -1;
68
0
    }
69
70
0
    if (prop_key_check("alias", k, len) == 0 && tmp) {
71
0
        ins->alias = tmp;
72
0
    }
73
0
    else if (prop_key_check("log_level", k, len) == 0 && tmp) {
74
0
        ret = flb_log_get_level_str(tmp);
75
0
        flb_sds_destroy(tmp);
76
0
        if (ret == -1) {
77
0
            return -1;
78
0
        }
79
0
        ins->log_level = ret;
80
0
    }
81
0
    else {
82
        /*
83
         * Create the property, we don't pass the value since we will
84
         * map it directly to avoid an extra memory allocation.
85
         */
86
0
        kv = flb_kv_item_create(&ins->properties, (char *) k, NULL);
87
0
        if (!kv) {
88
0
            if (tmp) {
89
0
                flb_sds_destroy(tmp);
90
0
            }
91
0
            return -1;
92
0
        }
93
0
        kv->val = tmp;
94
0
    }
95
96
0
    return 0;
97
0
}
98
99
const char *flb_custom_get_property(const char *key,
100
                                    struct flb_custom_instance *ins)
101
0
{
102
0
    return flb_kv_get_key_value(key, &ins->properties);
103
0
}
104
105
void flb_custom_instance_exit(struct flb_custom_instance *ins,
106
                              struct flb_config *config)
107
0
{
108
0
    struct flb_custom_plugin *p;
109
110
0
    p = ins->p;
111
0
    if (p->cb_exit && ins->context) {
112
0
        p->cb_exit(ins->context, config);
113
0
    }
114
0
}
115
116
/* Invoke exit call for the custom plugin */
117
void flb_custom_exit(struct flb_config *config)
118
0
{
119
0
    struct mk_list *tmp;
120
0
    struct mk_list *head;
121
0
    struct flb_custom_instance *ins;
122
0
    struct flb_custom_plugin *p;
123
124
0
    mk_list_foreach_safe(head, tmp, &config->customs) {
125
0
        ins = mk_list_entry(head, struct flb_custom_instance, _head);
126
0
        p = ins->p;
127
0
        if (!p) {
128
0
            continue;
129
0
        }
130
0
        flb_custom_instance_exit(ins, config);
131
0
        flb_custom_instance_destroy(ins);
132
0
    }
133
0
}
134
135
struct flb_custom_instance *flb_custom_new(struct flb_config *config,
136
                                           const char *custom, void *data)
137
0
{
138
0
    int id;
139
0
    struct mk_list *head;
140
0
    struct flb_custom_plugin *plugin;
141
0
    struct flb_custom_instance *instance = NULL;
142
143
0
    if (!custom) {
144
0
        return NULL;
145
0
    }
146
147
0
    mk_list_foreach(head, &config->custom_plugins) {
148
0
        plugin = mk_list_entry(head, struct flb_custom_plugin, _head);
149
0
        if (strcmp(plugin->name, custom) == 0) {
150
0
            break;
151
0
        }
152
0
        plugin = NULL;
153
0
    }
154
155
0
    if (!plugin) {
156
0
        return NULL;
157
0
    }
158
159
0
    instance = flb_calloc(1, sizeof(struct flb_custom_instance));
160
0
    if (!instance) {
161
0
        flb_errno();
162
0
        return NULL;
163
0
    }
164
0
    instance->config = config;
165
166
    /* Get an ID */
167
0
    id =  instance_id(config);
168
169
    /* format name (with instance id) */
170
0
    snprintf(instance->name, sizeof(instance->name) - 1,
171
0
             "%s.%i", plugin->name, id);
172
173
0
    instance->id    = id;
174
0
    instance->alias = NULL;
175
0
    instance->p     = plugin;
176
0
    instance->data  = data;
177
0
    instance->log_level = -1;
178
179
0
    mk_list_init(&instance->properties);
180
0
    mk_list_add(&instance->_head, &config->customs);
181
182
0
    return instance;
183
0
}
184
185
/* Return an instance name or alias */
186
const char *flb_custom_name(struct flb_custom_instance *ins)
187
0
{
188
0
    if (ins->alias) {
189
0
        return ins->alias;
190
0
    }
191
192
0
    return ins->name;
193
0
}
194
195
/* Initialize all custom plugins */
196
int flb_custom_init_all(struct flb_config *config)
197
0
{
198
0
    int ret;
199
0
    struct mk_list *tmp;
200
0
    struct mk_list *head;
201
0
    struct mk_list *config_map;
202
0
    struct flb_custom_plugin *p;
203
0
    struct flb_custom_instance *ins;
204
205
    /* Iterate all active custom instance plugins */
206
0
    mk_list_foreach_safe(head, tmp, &config->customs) {
207
0
        ins = mk_list_entry(head, struct flb_custom_instance, _head);
208
209
0
        if (ins->log_level == -1) {
210
0
            ins->log_level = config->log->level;
211
0
        }
212
213
0
        p = ins->p;
214
215
0
#ifdef FLB_HAVE_METRICS
216
        /* CMetrics */
217
0
        ins->cmt = cmt_create();
218
0
        if (!ins->cmt) {
219
0
            flb_error("[custom] could not create cmetrics context: %s",
220
0
                      flb_custom_name(ins));
221
0
            return -1;
222
0
        }
223
0
#endif
224
225
        /*
226
         * Before to call the initialization callback, make sure that the received
227
         * configuration parameters are valid if the plugin is registering a config map.
228
         */
229
0
        if (p->config_map) {
230
            /*
231
             * Create a dynamic version of the configmap that will be used by the specific
232
             * instance in question.
233
             */
234
0
            config_map = flb_config_map_create(config, p->config_map);
235
0
            if (!config_map) {
236
0
                flb_error("[custom] error loading config map for '%s' plugin",
237
0
                          p->name);
238
0
                return -1;
239
0
            }
240
0
            ins->config_map = config_map;
241
242
            /* Validate incoming properties against config map */
243
0
            ret = flb_config_map_properties_check(ins->p->name,
244
0
                                                  &ins->properties, ins->config_map);
245
0
            if (ret == -1) {
246
0
                if (config->program_name) {
247
0
                    flb_helper("try the command: %s -F %s -h\n",
248
0
                               config->program_name, ins->p->name);
249
0
                }
250
0
                flb_custom_instance_destroy(ins);
251
0
                return -1;
252
0
            }
253
0
        }
254
255
        /* Initialize the input */
256
0
        if (p->cb_init) {
257
0
            ret = p->cb_init(ins, config, ins->data);
258
0
            if (ret != 0) {
259
0
                flb_error("Failed initialize custom %s", ins->name);
260
0
                flb_custom_instance_destroy(ins);
261
0
                return -1;
262
0
            }
263
0
        }
264
0
    }
265
266
0
    return 0;
267
0
}
268
269
void flb_custom_instance_destroy(struct flb_custom_instance *ins)
270
0
{
271
0
    if (!ins) {
272
0
        return;
273
0
    }
274
275
    /* destroy config map */
276
0
    if (ins->config_map) {
277
0
        flb_config_map_destroy(ins->config_map);
278
0
    }
279
280
    /* release properties */
281
0
    flb_kv_release(&ins->properties);
282
283
0
    if (ins->alias) {
284
0
        flb_sds_destroy(ins->alias);
285
0
    }
286
287
0
#ifdef FLB_HAVE_METRICS
288
0
    if (ins->cmt) {
289
0
        cmt_destroy(ins->cmt);
290
0
    }
291
0
#endif
292
293
0
    mk_list_del(&ins->_head);
294
0
    flb_free(ins);
295
0
}
296
297
void flb_custom_set_context(struct flb_custom_instance *ins, void *context)
298
0
{
299
0
    ins->context = context;
300
0
}