Coverage Report

Created: 2024-09-19 07:08

/src/fluent-bit/src/http_server/api/v1/trace.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-2024 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_info.h>
21
#include <fluent-bit/flb_pack.h>
22
#include <fluent-bit/flb_input.h>
23
#include <fluent-bit/flb_filter.h>
24
#include <fluent-bit/flb_output.h>
25
#include <fluent-bit/flb_sds.h>
26
#include <fluent-bit/flb_http_server.h>
27
#include <fluent-bit/flb_lib.h>
28
#include <fluent-bit/flb_chunk_trace.h>
29
#include <fluent-bit/flb_kv.h>
30
#include <fluent-bit/flb_utils.h>
31
#include <msgpack.h>
32
33
0
#define STR_INPUTS "inputs"
34
0
#define STR_INPUTS_LEN (sizeof(STR_INPUTS)-1)
35
36
0
#define HTTP_FIELD_MESSAGE        "message"
37
0
#define HTTP_FIELD_MESSAGE_LEN    (sizeof(HTTP_FIELD_MESSAGE)-1)
38
0
#define HTTP_FIELD_STATUS         "status"
39
0
#define HTTP_FIELD_STATUS_LEN     (sizeof(HTTP_FIELD_STATUS)-1)
40
0
#define HTTP_FIELD_RETURNCODE     "returncode"
41
0
#define HTTP_FIELD_RETURNCODE_LEN (sizeof(HTTP_FIELD_RETURNCODE)-1)
42
43
0
#define HTTP_RESULT_OK                   "ok"
44
0
#define HTTP_RESULT_OK_LEN               (sizeof(HTTP_RESULT_OK)-1)
45
0
#define HTTP_RESULT_ERROR                "error"
46
0
#define HTTP_RESULT_ERROR_LEN            (sizeof(HTTP_RESULT_ERROR)-1)
47
0
#define HTTP_RESULT_NOTFOUND             "not found"
48
0
#define HTTP_RESULT_NOTFOUND_LEN         (sizeof(HTTP_RESULT_NOTFOUND)-1)
49
0
#define HTTP_RESULT_METHODNOTALLOWED     "method not allowed"
50
0
#define HTTP_RESULT_METHODNOTALLOWED_LEN (sizeof(HTTP_RESULT_METHODNOTALLOWED)-1)
51
0
#define HTTP_RESULT_UNKNOWNERROR         "unknown error"
52
0
#define HTTP_RESULT_UNKNOWNERROR_LEN     (sizeof(HTTP_RESULT_UNKNOWNERROR)-1)
53
54
static struct flb_input_instance *find_input(struct flb_hs *hs, const char *name, size_t nlen)
55
0
{
56
0
    struct mk_list *head;
57
0
    struct flb_input_instance *in;
58
59
60
0
    mk_list_foreach(head, &hs->config->inputs) {
61
0
        in = mk_list_entry(head, struct flb_input_instance, _head);
62
0
        if ((strlen(in->name) == nlen) && (strncmp(name, in->name, nlen) == 0)) {
63
0
            return in;
64
0
        }
65
0
        if (in->alias) {
66
0
            if ((strlen(in->alias) == nlen) && (strncmp(name, in->alias, nlen) == 0)) {
67
0
                return in;
68
0
            }
69
0
        }
70
0
    }
71
0
    return NULL;
72
0
}
73
74
static int enable_trace_input(struct flb_hs *hs, const char *name, ssize_t nlen, const char *prefix,
75
                              const char *output_name, struct mk_list *props)
76
0
{
77
0
    struct flb_input_instance *in;
78
79
0
    in = find_input(hs, name, nlen);
80
0
    if (in == NULL) {
81
0
        flb_error("unable to find input: [%d]%.*s", (int)nlen, (int)nlen, name);
82
0
        return 404;
83
0
    }
84
85
0
    flb_chunk_trace_context_new(in, output_name, prefix, NULL, props);
86
87
0
    if (in->chunk_trace_ctxt == NULL) {
88
0
        flb_error("unable to start tracing");
89
0
        return 503;
90
0
    }
91
92
0
    return 0;
93
0
}
94
95
static int disable_trace_input(struct flb_hs *hs, const char *name, size_t nlen)
96
0
{
97
0
    struct flb_input_instance *in;
98
99
100
0
    in = find_input(hs, name, nlen);
101
0
    if (in == NULL) {
102
0
        return 404;
103
0
    }
104
105
0
    if (in->chunk_trace_ctxt != NULL) {
106
0
        flb_chunk_trace_context_destroy(in);
107
0
    }
108
0
    return 201;
109
0
}
110
111
static flb_sds_t get_input_name(mk_request_t *request)
112
0
{
113
0
    const char base[] = "/api/v1/trace/";
114
115
116
0
    if (request->real_path.data == NULL) {
117
0
        return NULL;
118
0
    }
119
0
    if (request->real_path.len < sizeof(base)-1) {
120
0
        return NULL;
121
0
    }
122
123
0
    return flb_sds_create_len(&request->real_path.data[sizeof(base)-1],
124
0
                              request->real_path.len - (sizeof(base)-1));
125
0
}
126
127
static int http_disable_trace(mk_request_t *request, void *data,
128
                              const char *input_name, size_t input_nlen,
129
                              msgpack_packer *mp_pck)
130
0
{
131
0
    struct flb_hs *hs = data;
132
0
    int toggled_on = 503;
133
134
135
0
    toggled_on = disable_trace_input(hs, input_name, input_nlen);
136
0
    if (toggled_on < 300) {
137
0
        msgpack_pack_map(mp_pck, 1);
138
0
        msgpack_pack_str_with_body(mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
139
0
        msgpack_pack_str_with_body(mp_pck, HTTP_RESULT_OK, HTTP_RESULT_OK_LEN);
140
0
        return 201;
141
0
    }
142
143
0
    return toggled_on;
144
0
}
145
146
static int msgpack_params_enable_trace(struct flb_hs *hs, msgpack_unpacked *result,
147
                                       const char *input_name, ssize_t input_nlen)
148
0
{
149
0
    int ret = -1;
150
0
    int i;
151
0
    int x;
152
0
    flb_sds_t prefix = NULL;
153
0
    flb_sds_t output_name = NULL;
154
0
    int toggled_on = -1;
155
0
    msgpack_object *key;
156
0
    msgpack_object *val;
157
0
    struct mk_list *props = NULL;
158
0
    msgpack_object_kv *param;
159
0
    msgpack_object_str *param_key;
160
0
    msgpack_object_str *param_val;
161
162
163
0
    if (result->data.type == MSGPACK_OBJECT_MAP) {
164
0
        for (i = 0; i < result->data.via.map.size; i++) {
165
0
            key = &result->data.via.map.ptr[i].key;
166
0
            val = &result->data.via.map.ptr[i].val;
167
168
0
            if (key->type != MSGPACK_OBJECT_STR) {
169
0
                ret = -1;
170
0
                goto parse_error;
171
0
            }
172
173
0
            if (strncmp(key->via.str.ptr, "prefix", key->via.str.size) == 0) {
174
0
                if (val->type != MSGPACK_OBJECT_STR) {
175
0
                    ret = -1;
176
0
                    goto parse_error;
177
0
                }
178
0
                if (prefix != NULL) {
179
0
                    flb_sds_destroy(prefix);
180
0
                }
181
0
                prefix = flb_sds_create_len(val->via.str.ptr, val->via.str.size);
182
0
            }
183
0
            else if (strncmp(key->via.str.ptr, "output", key->via.str.size) == 0) {
184
0
                if (val->type != MSGPACK_OBJECT_STR) {
185
0
                    ret = -1;
186
0
                    goto parse_error;
187
0
                }
188
0
                if (output_name != NULL) {
189
0
                    flb_sds_destroy(output_name);
190
0
                }
191
0
                output_name = flb_sds_create_len(val->via.str.ptr, val->via.str.size);
192
0
            }
193
0
            else if (strncmp(key->via.str.ptr, "params", key->via.str.size) == 0) {
194
0
                if (val->type != MSGPACK_OBJECT_MAP) {
195
0
                    ret = -1;
196
0
                    goto parse_error;
197
0
                }
198
0
                if (props != NULL) {
199
0
                    flb_free(props);
200
0
                }
201
0
                props = flb_calloc(1, sizeof(struct mk_list));
202
0
                flb_kv_init(props);
203
0
                for (x = 0; x < val->via.map.size; x++) {
204
0
                    param = &val->via.map.ptr[x];
205
0
                    if (param->val.type != MSGPACK_OBJECT_STR) {
206
0
                        ret = -1;
207
0
                        goto parse_error;
208
0
                    }
209
0
                    if (param->key.type != MSGPACK_OBJECT_STR) {
210
0
                        ret = -1;
211
0
                        goto parse_error;
212
0
                    }
213
0
                    param_key = &param->key.via.str;
214
0
                    param_val = &param->val.via.str;
215
0
                    flb_kv_item_create_len(props,
216
0
                                          (char *)param_key->ptr, param_key->size,
217
0
                                          (char *)param_val->ptr, param_val->size);
218
0
                }
219
0
            }
220
0
        }
221
222
0
        if (output_name == NULL) {
223
0
            output_name = flb_sds_create("stdout");
224
0
        }
225
226
0
        toggled_on = enable_trace_input(hs, input_name, input_nlen, prefix, output_name, props);
227
0
        if (!toggled_on) {
228
0
            ret = -1;
229
0
            goto parse_error;
230
0
        }
231
0
    }
232
233
0
parse_error:
234
0
    if (prefix) flb_sds_destroy(prefix);
235
0
    if (output_name) flb_sds_destroy(output_name);
236
0
    if (props != NULL) {
237
0
        flb_kv_release(props);
238
0
        flb_free(props);
239
0
    }
240
0
    return ret;
241
0
}
242
243
static int http_enable_trace(mk_request_t *request, void *data,
244
                             const char *input_name, ssize_t input_nlen,
245
                             msgpack_packer *mp_pck)
246
0
{
247
0
    char *buf = NULL;
248
0
    size_t buf_size;
249
0
    msgpack_unpacked result;
250
0
    int ret = -1;
251
0
    int rc = -1;
252
0
    int i;
253
0
    int x;
254
0
    size_t off = 0;
255
0
    int root_type = MSGPACK_OBJECT_ARRAY;
256
0
    struct flb_hs *hs = data;
257
0
    flb_sds_t prefix = NULL;
258
0
    flb_sds_t output_name = NULL;
259
0
    msgpack_object *key;
260
0
    msgpack_object *val;
261
0
    struct mk_list *props = NULL;
262
0
    struct flb_chunk_trace_limit limit = { 0 };
263
0
    struct flb_input_instance *input_instance;
264
265
266
0
    if (request->method == MK_METHOD_GET) {
267
0
        ret = enable_trace_input(hs, input_name, input_nlen, "trace.", "stdout", NULL);
268
0
        if (ret == 0) {
269
0
                msgpack_pack_map(mp_pck, 1);
270
0
                msgpack_pack_str_with_body(mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
271
0
                msgpack_pack_str_with_body(mp_pck, HTTP_RESULT_OK, HTTP_RESULT_OK_LEN);
272
0
                return 200;
273
0
        }
274
0
        else {
275
0
            flb_error("unable to enable tracing for %.*s", (int)input_nlen, input_name);
276
0
            goto input_error;
277
0
        }
278
0
    }
279
280
0
    msgpack_unpacked_init(&result);
281
0
    rc = flb_pack_json(request->data.data, request->data.len, &buf, &buf_size,
282
0
                       &root_type, NULL);
283
0
    if (rc == -1) {
284
0
        ret = 503;
285
0
        flb_error("unable to parse json parameters");
286
0
        goto unpack_error;
287
0
    }
288
289
0
    rc = msgpack_unpack_next(&result, buf, buf_size, &off);
290
0
    if (rc != MSGPACK_UNPACK_SUCCESS) {
291
0
        ret = 503;
292
0
        flb_error("unable to unpack msgpack parameters for %.*s", (int)input_nlen, input_name);
293
0
        goto unpack_error;
294
0
    }
295
296
0
    if (result.data.type == MSGPACK_OBJECT_MAP) {
297
0
        for (i = 0; i < result.data.via.map.size; i++) {
298
0
            key = &result.data.via.map.ptr[i].key;
299
0
            val = &result.data.via.map.ptr[i].val;
300
301
0
            if (key->type != MSGPACK_OBJECT_STR) {
302
0
                ret = 503;
303
0
                flb_error("non string key in parameters");
304
0
                goto parse_error;
305
0
            }
306
307
0
            if (strncmp(key->via.str.ptr, "prefix", key->via.str.size) == 0) {
308
0
                if (val->type != MSGPACK_OBJECT_STR) {
309
0
                    ret = 503;
310
0
                    flb_error("prefix is not a string");
311
0
                    goto parse_error;
312
0
                }
313
0
                if (prefix != NULL) {
314
0
                    flb_sds_destroy(prefix);
315
0
                }
316
0
                prefix = flb_sds_create_len(val->via.str.ptr, val->via.str.size);
317
0
            }
318
0
            else if (strncmp(key->via.str.ptr, "output", key->via.str.size) == 0) {
319
0
                if (val->type != MSGPACK_OBJECT_STR) {
320
0
                    ret = 503;
321
0
                    flb_error("output is not a string");
322
0
                    goto parse_error;
323
0
                }
324
0
                if (output_name != NULL) {
325
0
                    flb_sds_destroy(output_name);
326
0
                }
327
0
                output_name = flb_sds_create_len(val->via.str.ptr, val->via.str.size);
328
0
            }
329
0
            else if (strncmp(key->via.str.ptr, "params", key->via.str.size) == 0) {
330
0
                if (val->type != MSGPACK_OBJECT_MAP) {
331
0
                    ret = 503;
332
0
                    flb_error("output params is not a maps");
333
0
                    goto parse_error;
334
0
                }
335
0
                props = flb_calloc(1, sizeof(struct mk_list));
336
0
                flb_kv_init(props);
337
0
                for (x = 0; x < val->via.map.size; x++) {
338
0
                    if (val->via.map.ptr[x].val.type != MSGPACK_OBJECT_STR) {
339
0
                        ret = 503;
340
0
                        flb_error("output parameter key is not a string");
341
0
                        goto parse_error;
342
0
                    }
343
0
                    if (val->via.map.ptr[x].key.type != MSGPACK_OBJECT_STR) {
344
0
                        ret = 503;
345
0
                        flb_error("output parameter value is not a string");
346
0
                        goto parse_error;
347
0
                    }
348
0
                    flb_kv_item_create_len(props,
349
0
                                            (char *)val->via.map.ptr[x].key.via.str.ptr, val->via.map.ptr[x].key.via.str.size,
350
0
                                            (char *)val->via.map.ptr[x].val.via.str.ptr, val->via.map.ptr[x].val.via.str.size);
351
0
                }
352
0
            }
353
0
            else if (strncmp(key->via.str.ptr, "limit", key->via.str.size) == 0) {
354
0
                if (val->type != MSGPACK_OBJECT_MAP) {
355
0
                    ret = 503;
356
0
                    flb_error("limit must be a map of limit types");
357
0
                    goto parse_error;
358
0
                }
359
0
                if (val->via.map.size != 1) {
360
0
                    ret = 503;
361
0
                    flb_error("limit must have a single limit type");
362
0
                    goto parse_error;
363
0
                }
364
0
                if (val->via.map.ptr[0].key.type != MSGPACK_OBJECT_STR) {
365
0
                    ret = 503;
366
0
                    flb_error("limit type (key) must be a string");
367
0
                    goto parse_error;
368
0
                }
369
0
                if (val->via.map.ptr[0].val.type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
370
0
                    ret = 503;
371
0
                    flb_error("limit type must be an integer");
372
0
                    goto parse_error;
373
0
                }
374
0
                if (strncmp(val->via.map.ptr[0].key.via.str.ptr, "seconds", val->via.map.ptr[0].key.via.str.size) == 0) {
375
0
                    limit.type = FLB_CHUNK_TRACE_LIMIT_TIME;
376
0
                    limit.seconds = val->via.map.ptr[0].val.via.u64;
377
0
                }
378
0
                else if (strncmp(val->via.map.ptr[0].key.via.str.ptr, "count", val->via.map.ptr[0].key.via.str.size) == 0) {
379
0
                    limit.type = FLB_CHUNK_TRACE_LIMIT_COUNT;
380
0
                    limit.count = val->via.map.ptr[0].val.via.u64;
381
0
                }
382
0
                else {
383
0
                    ret = 503;
384
0
                    flb_error("unknown limit type");
385
0
                    goto parse_error;
386
0
                }
387
0
            }
388
0
        }
389
390
0
        if (output_name == NULL) {
391
0
            output_name = flb_sds_create("stdout");
392
0
        }
393
394
0
        ret = enable_trace_input(hs, input_name, input_nlen, prefix, output_name, props);
395
0
        if (ret != 0) {
396
0
            flb_error("error when enabling tracing");
397
0
            goto parse_error;
398
0
        }
399
400
0
        if (limit.type != 0) {
401
0
            input_instance = find_input(hs, input_name, input_nlen);
402
0
            if (limit.type == FLB_CHUNK_TRACE_LIMIT_TIME) {
403
0
                flb_chunk_trace_context_set_limit(input_instance->chunk_trace_ctxt, limit.type, limit.seconds);
404
0
            }
405
0
            else if (limit.type == FLB_CHUNK_TRACE_LIMIT_COUNT) {
406
0
                flb_chunk_trace_context_set_limit(input_instance->chunk_trace_ctxt, limit.type, limit.count);
407
0
            }
408
0
        }
409
0
    }
410
411
0
    msgpack_pack_map(mp_pck, 1);
412
0
    msgpack_pack_str_with_body(mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
413
0
    msgpack_pack_str_with_body(mp_pck, HTTP_RESULT_OK, HTTP_RESULT_OK_LEN);
414
415
0
    ret = 200;
416
0
parse_error:
417
0
    if (prefix) flb_sds_destroy(prefix);
418
0
    if (output_name) flb_sds_destroy(output_name);
419
0
    if (props != NULL) {
420
0
        flb_kv_release(props);
421
0
        flb_free(props);
422
0
    }
423
0
unpack_error:
424
0
    msgpack_unpacked_destroy(&result);
425
0
    if (buf != NULL) {
426
0
        flb_free(buf);
427
0
    }
428
0
input_error:
429
0
    return ret;
430
0
}
431
432
static void cb_trace(mk_request_t *request, void *data)
433
0
{
434
0
    flb_sds_t out_buf;
435
0
    msgpack_sbuffer mp_sbuf;
436
0
    msgpack_packer mp_pck;
437
0
    int response = 404;
438
0
    flb_sds_t input_name = NULL;
439
440
441
    /* initialize buffers */
442
0
    msgpack_sbuffer_init(&mp_sbuf);
443
0
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);
444
445
0
    input_name = get_input_name(request);
446
0
    if (input_name == NULL) {
447
0
        response = 404;
448
0
        goto error;
449
0
    }
450
451
0
    if (request->method == MK_METHOD_POST || request->method == MK_METHOD_GET) {
452
0
        response = http_enable_trace(request, data, input_name, flb_sds_len(input_name), &mp_pck);
453
0
    }
454
0
    else if (request->method == MK_METHOD_DELETE) {
455
0
        response = http_disable_trace(request, data, input_name, flb_sds_len(input_name), &mp_pck);
456
0
    }
457
0
error:
458
0
    if (response == 404) {
459
0
        msgpack_pack_map(&mp_pck, 1);
460
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
461
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_NOTFOUND, HTTP_RESULT_NOTFOUND_LEN);
462
0
    }
463
0
    else if (response == 503) {
464
0
        msgpack_pack_map(&mp_pck, 1);
465
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
466
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_ERROR, HTTP_RESULT_ERROR_LEN);
467
0
    }
468
469
0
    if (input_name != NULL) {
470
0
        flb_sds_destroy(input_name);
471
0
    }
472
473
    /* Export to JSON */
474
0
    out_buf = flb_msgpack_raw_to_json_sds(mp_sbuf.data, mp_sbuf.size);
475
0
    if (out_buf == NULL) {
476
0
        mk_http_status(request, 503);
477
0
        mk_http_done(request);
478
0
        return;
479
0
    }
480
481
0
    mk_http_status(request, response);
482
0
    mk_http_send(request, out_buf, flb_sds_len(out_buf), NULL);
483
0
    mk_http_done(request);
484
485
0
    msgpack_sbuffer_destroy(&mp_sbuf);
486
0
    flb_sds_destroy(out_buf);
487
0
}
488
489
static void cb_traces(mk_request_t *request, void *data)
490
0
{
491
0
    flb_sds_t out_buf;
492
0
    msgpack_sbuffer mp_sbuf;
493
0
    msgpack_packer mp_pck;
494
0
    int ret;
495
0
    char *buf = NULL;
496
0
    size_t buf_size;
497
0
    int root_type = MSGPACK_OBJECT_ARRAY;
498
0
    msgpack_unpacked result;
499
0
    flb_sds_t error_msg = NULL;
500
0
    int response = 200;
501
0
    const char *input_name;
502
0
    ssize_t input_nlen;
503
0
    msgpack_object_array *inputs = NULL;
504
0
    size_t off = 0;
505
0
    int i;
506
507
    /* initialize buffers */
508
0
    msgpack_sbuffer_init(&mp_sbuf);
509
0
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);
510
511
0
    msgpack_unpacked_init(&result);
512
0
    ret = flb_pack_json(request->data.data, request->data.len, &buf, &buf_size,
513
0
                        &root_type, NULL);
514
0
    if (ret == -1) {
515
0
        goto unpack_error;
516
0
    }
517
518
0
    ret = msgpack_unpack_next(&result, buf, buf_size, &off);
519
0
    if (ret != MSGPACK_UNPACK_SUCCESS) {
520
0
        ret = -1;
521
0
        error_msg = flb_sds_create("unfinished input");
522
0
        goto unpack_error;
523
0
    }
524
525
0
    if (result.data.type != MSGPACK_OBJECT_MAP) {
526
0
        response = 503;
527
0
        error_msg = flb_sds_create("input is not an object");
528
0
        goto unpack_error;
529
0
    }
530
531
0
    for (i = 0; i < result.data.via.map.size; i++) {
532
0
        if (result.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) {
533
0
            continue;
534
0
        }
535
0
        if (result.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) {
536
0
            continue;
537
0
        }
538
0
        if (result.data.via.map.ptr[i].key.via.str.size < STR_INPUTS_LEN) {
539
0
            continue;
540
0
        }
541
0
        if (strncmp(result.data.via.map.ptr[i].key.via.str.ptr, STR_INPUTS, STR_INPUTS_LEN)) {
542
0
            continue;
543
0
        }
544
0
        inputs = &result.data.via.map.ptr[i].val.via.array;
545
0
    }
546
547
0
    if (inputs == NULL) {
548
0
        response = 503;
549
0
        error_msg = flb_sds_create("inputs not found");
550
0
        goto unpack_error;
551
0
    }
552
553
0
    msgpack_pack_map(&mp_pck, 2);
554
555
0
    msgpack_pack_str_with_body(&mp_pck, STR_INPUTS, STR_INPUTS_LEN);
556
0
    msgpack_pack_map(&mp_pck, inputs->size);
557
558
0
    for (i = 0; i < inputs->size; i++) {
559
560
0
        if (inputs->ptr[i].type != MSGPACK_OBJECT_STR || inputs->ptr[i].via.str.ptr == NULL) {
561
0
            response = 503;
562
0
            error_msg = flb_sds_create("invalid input");
563
0
            msgpack_sbuffer_clear(&mp_sbuf);
564
0
            goto unpack_error;
565
0
        }
566
0
    }
567
568
0
    for (i = 0; i < inputs->size; i++) {
569
570
0
        input_name = inputs->ptr[i].via.str.ptr;
571
0
        input_nlen = inputs->ptr[i].via.str.size;
572
573
0
        msgpack_pack_str_with_body(&mp_pck, input_name, input_nlen);
574
575
0
        if (request->method == MK_METHOD_POST) {
576
577
0
            ret = msgpack_params_enable_trace((struct flb_hs *)data, &result,
578
0
                                              input_name, input_nlen);
579
580
0
            if (ret != 0) {
581
0
                msgpack_pack_map(&mp_pck, 2);
582
0
                msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
583
0
                msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_ERROR, HTTP_RESULT_ERROR_LEN);
584
0
                msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_RETURNCODE,
585
0
                                           HTTP_FIELD_RETURNCODE_LEN);
586
0
                msgpack_pack_int64(&mp_pck, ret);
587
0
            }
588
0
            else {
589
0
                msgpack_pack_map(&mp_pck, 1);
590
0
                msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
591
0
                msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_OK, HTTP_RESULT_OK_LEN);
592
0
            }
593
0
        }
594
0
        else if (request->method == MK_METHOD_DELETE) {
595
0
            disable_trace_input((struct flb_hs *)data, input_name, input_nlen);
596
0
            msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
597
0
            msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_OK, HTTP_RESULT_OK_LEN);
598
0
        }
599
0
        else {
600
0
            msgpack_pack_map(&mp_pck, 2);
601
0
            msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
602
0
            msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_ERROR, HTTP_RESULT_ERROR_LEN);
603
0
            msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_MESSAGE, HTTP_FIELD_MESSAGE_LEN);
604
0
            msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_METHODNOTALLOWED,
605
0
                                       HTTP_RESULT_METHODNOTALLOWED_LEN);
606
0
        }
607
0
    }
608
609
0
    msgpack_pack_str_with_body(&mp_pck, "result", strlen("result"));
610
0
unpack_error:
611
0
    if (buf != NULL) {
612
0
        flb_free(buf);
613
0
    }
614
0
    msgpack_unpacked_destroy(&result);
615
0
    if (response == 404) {
616
0
        msgpack_pack_map(&mp_pck, 1);
617
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
618
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_NOTFOUND, HTTP_RESULT_NOTFOUND_LEN);
619
0
    }
620
0
    else if (response == 503) {
621
0
        msgpack_pack_map(&mp_pck, 2);
622
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
623
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_OK, HTTP_RESULT_OK_LEN);
624
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_MESSAGE, HTTP_FIELD_MESSAGE_LEN);
625
0
        if (error_msg) {
626
0
            msgpack_pack_str_with_body(&mp_pck, error_msg, flb_sds_len(error_msg));
627
0
            flb_sds_destroy(error_msg);
628
0
        }
629
0
        else {
630
0
            msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_UNKNOWNERROR,
631
0
                                       HTTP_RESULT_UNKNOWNERROR_LEN);
632
0
        }
633
0
    }
634
0
    else {
635
0
        msgpack_pack_map(&mp_pck, 1);
636
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_FIELD_STATUS, HTTP_FIELD_STATUS_LEN);
637
0
        msgpack_pack_str_with_body(&mp_pck, HTTP_RESULT_OK, HTTP_RESULT_OK_LEN);
638
0
    }
639
640
    /* Export to JSON */
641
0
    out_buf = flb_msgpack_raw_to_json_sds(mp_sbuf.data, mp_sbuf.size);
642
0
    if (out_buf == NULL) {
643
0
        out_buf = flb_sds_create("serialization error");
644
0
    }
645
0
    msgpack_sbuffer_destroy(&mp_sbuf);
646
647
0
    mk_http_status(request, response);
648
0
    mk_http_send(request,
649
0
                 out_buf, flb_sds_len(out_buf), NULL);
650
0
    mk_http_done(request);
651
652
0
    flb_sds_destroy(out_buf);
653
0
}
654
655
/* Perform registration */
656
int api_v1_trace(struct flb_hs *hs)
657
0
{
658
0
    if (hs->config->enable_chunk_trace == FLB_TRUE) {
659
0
        mk_vhost_handler(hs->ctx, hs->vid, "/api/v1/traces/", cb_traces, hs);
660
0
        mk_vhost_handler(hs->ctx, hs->vid, "/api/v1/trace/*", cb_trace, hs);
661
0
    }
662
0
    return 0;
663
0
}