/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 | } |