Coverage Report

Created: 2025-01-28 07:34

/src/fluent-bit/plugins/processor_labels/labels.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 <stdio.h>
21
22
#include <fluent-bit/flb_filter.h>
23
#include <fluent-bit/flb_processor_plugin.h>
24
#include <fluent-bit/flb_utils.h>
25
#include <fluent-bit/flb_time.h>
26
#include <fluent-bit/flb_hash.h>
27
#include <fluent-bit/flb_pack.h>
28
#include <fluent-bit/flb_processor.h>
29
#include <fluent-bit/flb_log_event_decoder.h>
30
#include <fluent-bit/flb_log_event_encoder.h>
31
32
#include <cmetrics/cmetrics.h>
33
#include <cmetrics/cmt_histogram.h>
34
#include <cmetrics/cmt_summary.h>
35
#include <cmetrics/cmt_untyped.h>
36
#include <cmetrics/cmt_counter.h>
37
#include <cmetrics/cmt_gauge.h>
38
#include <cmetrics/cmt_map.h>
39
40
#include <cfl/cfl.h>
41
42
#define PROMOTE_STATIC_METRICS_ON_LABEL_INSERT
43
44
typedef int (*label_transformer)(struct cmt_metric *, cfl_sds_t *value);
45
46
struct internal_processor_context {
47
    struct mk_list *update_list;
48
    struct mk_list *insert_list;
49
    struct mk_list *upsert_list;
50
    struct mk_list *delete_list;
51
    struct mk_list *hash_list;
52
53
    /* internal labels ready to append */
54
    struct cfl_list update_labels;
55
    struct cfl_list insert_labels;
56
    struct cfl_list upsert_labels;
57
    struct mk_list  delete_labels;
58
    struct mk_list  hash_labels;
59
60
    struct flb_processor_instance *instance;
61
    struct flb_config *config;
62
};
63
64
65
/*
66
 * CMETRICS
67
 */
68
69
static void cmt_label_destroy(struct cmt_label *label)
70
0
{
71
0
    if (label != NULL) {
72
0
        if (!cfl_list_entry_is_orphan(&label->_head)) {
73
0
            cfl_list_del(&label->_head);
74
0
        }
75
76
0
        if (label->key != NULL) {
77
0
            cfl_sds_destroy(label->key);
78
0
        }
79
80
0
        if (label->val != NULL) {
81
0
            cfl_sds_destroy(label->val);
82
0
        }
83
84
0
        free(label);
85
0
    }
86
0
}
87
88
/* we can't use flb_* memory functions here because this will
89
 * be released by cmetrics using the standard allocator.
90
 */
91
92
static struct cmt_map_label *cmt_map_label_create(char *name)
93
0
{
94
0
    struct cmt_map_label *label;
95
96
0
    label = calloc(1, sizeof(struct cmt_map_label));
97
98
0
    if (label != NULL) {
99
0
        label->name = cfl_sds_create(name);
100
101
0
        if (label->name == NULL) {
102
0
            free(label);
103
104
0
            label = NULL;
105
0
        }
106
107
0
    }
108
109
0
    return label;
110
0
}
111
112
static void cmt_map_label_destroy(struct cmt_map_label *label)
113
0
{
114
0
    if (label != NULL) {
115
0
        if (!cfl_list_entry_is_orphan(&label->_head)) {
116
0
            cfl_list_del(&label->_head);
117
0
        }
118
119
0
        if (label->name != NULL) {
120
0
            cfl_sds_destroy(label->name);
121
0
        }
122
123
0
        free(label);
124
0
    }
125
0
}
126
127
static struct cmt_metric *map_metric_create(uint64_t hash,
128
                                            int labels_count, char **labels_val)
129
0
{
130
0
    int i;
131
0
    char *name;
132
0
    struct cmt_metric *metric;
133
0
    struct cmt_map_label *label;
134
135
0
    metric = calloc(1, sizeof(struct cmt_metric));
136
0
    if (!metric) {
137
0
        cmt_errno();
138
0
        return NULL;
139
0
    }
140
0
    cfl_list_init(&metric->labels);
141
0
    metric->val = 0.0;
142
0
    metric->hash = hash;
143
144
0
    for (i = 0; i < labels_count; i++) {
145
0
        label = malloc(sizeof(struct cmt_map_label));
146
0
        if (!label) {
147
0
            cmt_errno();
148
0
            goto error;
149
0
        }
150
151
0
        name = labels_val[i];
152
0
        label->name = cfl_sds_create(name);
153
0
        if (!label->name) {
154
0
            cmt_errno();
155
0
            free(label);
156
0
            goto error;
157
0
        }
158
0
        cfl_list_add(&label->_head, &metric->labels);
159
0
    }
160
161
0
    return metric;
162
163
0
 error:
164
0
    free(metric);
165
0
    return NULL;
166
0
}
167
168
static void map_metric_destroy(struct cmt_metric *metric)
169
0
{
170
0
    struct cfl_list *tmp;
171
0
    struct cfl_list *head;
172
0
    struct cmt_map_label *label;
173
174
0
    cfl_list_foreach_safe(head, tmp, &metric->labels) {
175
0
        label = cfl_list_entry(head, struct cmt_map_label, _head);
176
0
        cfl_sds_destroy(label->name);
177
0
        cfl_list_del(&label->_head);
178
0
        free(label);
179
0
    }
180
181
0
    if (metric->hist_buckets) {
182
0
        free(metric->hist_buckets);
183
0
    }
184
0
    if (metric->sum_quantiles) {
185
0
        free(metric->sum_quantiles);
186
0
    }
187
188
0
    cfl_list_del(&metric->_head);
189
0
    free(metric);
190
0
}
191
192
193
/*
194
 * LOCAL
195
 */
196
static int hex_encode(unsigned char *input_buffer,
197
                      size_t input_length,
198
                      cfl_sds_t *output_buffer)
199
0
{
200
0
    const char hex[] = "0123456789abcdef";
201
0
    cfl_sds_t  result;
202
0
    size_t     index;
203
204
0
    if (cfl_sds_alloc(*output_buffer) <= (input_length * 2)) {
205
0
        result = cfl_sds_increase(*output_buffer,
206
0
                                  (input_length * 2) -
207
0
                                  cfl_sds_alloc(*output_buffer));
208
209
0
        if (result == NULL) {
210
0
            return FLB_FALSE;
211
0
        }
212
213
0
        *output_buffer = result;
214
0
    }
215
216
0
    for (index = 0; index < input_length; index++) {
217
0
        (*output_buffer)[index * 2 + 0] = hex[(input_buffer[index] >> 4) & 0xF];
218
0
        (*output_buffer)[index * 2 + 1] = hex[(input_buffer[index] >> 0) & 0xF];
219
0
    }
220
221
0
    cfl_sds_set_len(*output_buffer, input_length * 2);
222
223
0
    (*output_buffer)[index * 2] = '\0';
224
225
0
    return FLB_TRUE;
226
0
}
227
228
static int process_label_modification_list_setting(
229
                struct flb_processor_instance *plugin_instance,
230
                const char *setting_name,
231
                struct mk_list *source_list,
232
                struct mk_list *destination_list)
233
0
{
234
0
    struct flb_config_map_val *source_entry;
235
0
    struct mk_list            *iterator;
236
0
    int                        result;
237
238
0
    if (source_list == NULL ||
239
0
        mk_list_is_empty(source_list) == 0) {
240
241
0
        return 0;
242
0
    }
243
244
0
    flb_config_map_foreach(iterator, source_entry, source_list) {
245
0
        result = flb_slist_add(destination_list, source_entry->val.str);
246
247
0
        if (result != 0) {
248
0
            flb_plg_error(plugin_instance,
249
0
                          "could not append label name %s\n",
250
0
                          source_entry->val.str);
251
252
0
            return -1;
253
0
        }
254
0
    }
255
256
0
    return 0;
257
0
}
258
259
static int process_label_modification_kvlist_setting(
260
                struct flb_processor_instance *plugin_instance,
261
                const char *setting_name,
262
                struct mk_list *source_list,
263
                struct cfl_list *destination_list)
264
0
{
265
0
    struct cfl_kv             *processed_pair;
266
0
    struct flb_config_map_val *source_entry;
267
0
    struct mk_list            *iterator;
268
0
    struct flb_slist_entry    *value;
269
0
    struct flb_slist_entry    *key;
270
271
0
    if (source_list == NULL ||
272
0
        mk_list_is_empty(source_list) == 0) {
273
274
0
        return 0;
275
0
    }
276
277
0
    flb_config_map_foreach(iterator, source_entry, source_list) {
278
0
        if (mk_list_size(source_entry->val.list) != 2) {
279
0
            flb_plg_error(plugin_instance,
280
0
                          "'%s' expects a key and a value, "
281
0
                          "e.g: '%s version 1.8.0'",
282
0
                          setting_name, setting_name);
283
284
0
            return -1;
285
0
        }
286
287
0
        key = mk_list_entry_first(source_entry->val.list,
288
0
                                  struct flb_slist_entry, _head);
289
290
0
        value = mk_list_entry_last(source_entry->val.list,
291
0
                                   struct flb_slist_entry, _head);
292
293
0
        processed_pair = cfl_kv_item_create(destination_list,
294
0
                                            key->str,
295
0
                                            value->str);
296
297
0
        if (processed_pair == NULL) {
298
0
            flb_plg_error(plugin_instance,
299
0
                          "could not append label %s=%s\n",
300
0
                          key->str,
301
0
                          value->str);
302
303
0
            return -1;
304
0
        }
305
0
    }
306
307
0
    return 0;
308
0
}
309
310
static void destroy_context(struct internal_processor_context *context)
311
0
{
312
0
    if (context != NULL) {
313
0
        cfl_kv_release(&context->update_labels);
314
0
        cfl_kv_release(&context->insert_labels);
315
0
        cfl_kv_release(&context->upsert_labels);
316
0
        flb_slist_destroy(&context->delete_labels);
317
0
        flb_slist_destroy(&context->hash_labels);
318
319
0
        flb_free(context);
320
0
    }
321
0
}
322
323
static struct internal_processor_context *
324
        create_context(struct flb_processor_instance *processor_instance,
325
                       struct flb_config *config)
326
0
{
327
0
    struct internal_processor_context *context;
328
0
    int                                result;
329
330
0
    context = flb_calloc(1, sizeof(struct internal_processor_context));
331
332
0
    if (context != NULL) {
333
0
        context->instance = processor_instance;
334
0
        context->config = config;
335
336
0
        cfl_kv_init(&context->update_labels);
337
0
        cfl_kv_init(&context->insert_labels);
338
0
        cfl_kv_init(&context->upsert_labels);
339
0
        flb_slist_create(&context->delete_labels);
340
0
        flb_slist_create(&context->hash_labels);
341
342
0
        result = flb_processor_instance_config_map_set(processor_instance, (void *) context);
343
344
0
        if (result == 0) {
345
0
            result = process_label_modification_kvlist_setting(processor_instance,
346
0
                                                               "update",
347
0
                                                               context->update_list,
348
0
                                                               &context->update_labels);
349
0
        }
350
351
0
        if (result == 0) {
352
0
            result = process_label_modification_kvlist_setting(processor_instance,
353
0
                                                               "insert",
354
0
                                                               context->insert_list,
355
0
                                                               &context->insert_labels);
356
0
        }
357
358
0
        if (result == 0) {
359
0
            result = process_label_modification_kvlist_setting(processor_instance,
360
0
                                                               "upsert",
361
0
                                                               context->upsert_list,
362
0
                                                               &context->upsert_labels);
363
0
        }
364
365
0
        if (result == 0) {
366
0
            result = process_label_modification_list_setting(processor_instance,
367
0
                                                             "delete",
368
0
                                                             context->delete_list,
369
0
                                                             &context->delete_labels);
370
0
        }
371
372
0
        if (result == 0) {
373
0
            result = process_label_modification_list_setting(processor_instance,
374
0
                                                             "hash",
375
0
                                                             context->hash_list,
376
0
                                                             &context->hash_labels);
377
0
        }
378
379
0
        if (result != 0) {
380
0
            destroy_context(context);
381
382
0
            context = NULL;
383
0
        }
384
0
    }
385
0
    else {
386
0
        flb_errno();
387
0
    }
388
389
0
    return context;
390
0
}
391
392
static int cb_init(struct flb_processor_instance *processor_instance,
393
                   void *source_plugin_instance,
394
                   int source_plugin_type,
395
                   struct flb_config *config)
396
0
{
397
0
    processor_instance->context = (void *) create_context(
398
0
                                            processor_instance, config);
399
400
0
    if (processor_instance->context == NULL) {
401
0
        return FLB_PROCESSOR_FAILURE;
402
0
    }
403
404
0
    return FLB_PROCESSOR_SUCCESS;
405
0
}
406
407
408
static int cb_exit(struct flb_processor_instance *processor_instance, void *data)
409
0
{
410
0
    if (processor_instance != NULL && data != NULL) {
411
0
        destroy_context(data);
412
0
    }
413
414
0
    return FLB_PROCESSOR_SUCCESS;
415
0
}
416
417
static int metrics_context_contains_static_label(struct cmt *metrics_context,
418
                                                 char *label_name)
419
0
{
420
0
    struct cfl_list  *label_iterator;
421
0
    struct cmt_label *label;
422
423
0
    cfl_list_foreach(label_iterator, &metrics_context->static_labels->list) {
424
0
        label = cfl_list_entry(label_iterator,
425
0
                               struct cmt_label, _head);
426
427
0
        if (strcasecmp(label_name, label->key) == 0) {
428
0
            return FLB_TRUE;
429
0
        }
430
0
    }
431
432
0
    return FLB_FALSE;
433
0
}
434
435
static int metrics_context_insert_static_label(struct cmt *metrics_context,
436
                                               char *label_name,
437
                                               char *label_value)
438
0
{
439
0
    if (cmt_label_add(metrics_context, label_name, label_value) != 0) {
440
0
        return FLB_FALSE;
441
0
    }
442
443
0
    return FLB_TRUE;
444
0
}
445
446
static int metrics_context_update_static_label(struct cmt *metrics_context,
447
                                               char *label_name,
448
                                               char *label_value)
449
0
{
450
0
    struct cfl_list  *iterator;
451
0
    cfl_sds_t         result;
452
0
    struct cmt_label *label;
453
454
0
    cfl_list_foreach(iterator, &metrics_context->static_labels->list) {
455
0
        label = cfl_list_entry(iterator,
456
0
                               struct cmt_label, _head);
457
458
0
        if (strcasecmp(label_name, label->key) == 0) {
459
0
            cfl_sds_set_len(label->val, 0);
460
461
0
            result = cfl_sds_cat(label->val, label_value, strlen(label_value));
462
463
0
            if (result == NULL) {
464
0
                return FLB_FALSE;
465
0
            }
466
467
0
            label->val = result;
468
469
0
            return FLB_TRUE;
470
0
        }
471
0
    }
472
473
0
    return FLB_FALSE;
474
0
}
475
476
static int metrics_context_transform_static_label(struct cmt *metrics_context,
477
                                                  char *label_name,
478
                                                  label_transformer transformer)
479
0
{
480
0
    struct cfl_list  *iterator;
481
0
    struct cmt_label *label;
482
483
0
    cfl_list_foreach(iterator, &metrics_context->static_labels->list) {
484
0
        label = cfl_list_entry(iterator,
485
0
                               struct cmt_label, _head);
486
487
0
        if (strcasecmp(label_name, label->key) == 0) {
488
0
            return transformer(NULL, &label->val);
489
0
        }
490
0
    }
491
492
0
    return FLB_FALSE;
493
0
}
494
495
static int metrics_context_upsert_static_label(struct cmt *metrics_context,
496
                                               char *label_name,
497
                                               char *label_value)
498
0
{
499
0
    int result;
500
501
0
    result = metrics_context_contains_static_label(metrics_context,
502
0
                                                   label_name);
503
504
0
    if (result == FLB_TRUE) {
505
0
        return metrics_context_update_static_label(metrics_context,
506
0
                                                   label_name,
507
0
                                                   label_value);
508
0
    }
509
510
0
    return metrics_context_insert_static_label(metrics_context,
511
0
                                               label_name,
512
0
                                               label_value);
513
0
}
514
515
static int metrics_context_remove_static_label(struct cmt *metrics_context,
516
                                               char *label_name)
517
0
{
518
0
    struct cfl_list  *iterator;
519
0
    struct cmt_label *label;
520
521
0
    cfl_list_foreach(iterator,
522
0
                     &metrics_context->static_labels->list) {
523
0
        label = cfl_list_entry(iterator, struct cmt_label, _head);
524
525
0
        if (strcasecmp(label_name, label->key) == 0) {
526
0
            cmt_label_destroy(label);
527
528
0
            return FLB_TRUE;
529
0
        }
530
0
    }
531
532
0
    return FLB_FALSE;
533
0
}
534
535
static ssize_t metrics_map_get_label_index(struct cmt_map *map, char *label_name)
536
0
{
537
0
    struct cfl_list      *iterator;
538
0
    struct cmt_map_label *label;
539
0
    ssize_t               index;
540
541
0
    index = 0;
542
543
0
    cfl_list_foreach(iterator, &map->label_keys) {
544
0
        label = cfl_list_entry(iterator, struct cmt_map_label, _head);
545
546
0
        if (strcasecmp(label_name, label->name) == 0) {
547
0
            return index;
548
0
        }
549
550
0
        index++;
551
0
    }
552
553
0
    return -1;
554
0
}
555
556
static ssize_t metrics_map_insert_label_name(struct cmt_map *map, char *label_name)
557
0
{
558
0
    struct cmt_map_label *label;
559
0
    ssize_t               index;
560
561
0
    label = cmt_map_label_create(label_name);
562
563
0
    if (label == NULL) {
564
0
        return -1;
565
0
    }
566
567
0
    map->label_count++;
568
569
0
    cfl_list_add(&label->_head, &map->label_keys);
570
571
0
    index = (ssize_t) cfl_list_size(&map->label_keys);
572
0
    index--;
573
574
0
    return index;
575
0
}
576
577
static int metrics_map_contains_label(struct cmt_map *map, char *label_name)
578
0
{
579
0
    ssize_t result;
580
581
0
    result = metrics_map_get_label_index(map, label_name);
582
583
0
    if (result != -1) {
584
0
        return FLB_TRUE;
585
0
    }
586
587
0
    return FLB_FALSE;
588
0
}
589
590
static int metrics_map_remove_label_name(struct cmt_map *map,
591
                                         size_t label_index)
592
0
{
593
0
    struct cfl_list      *iterator;
594
0
    struct cmt_map_label *label;
595
0
    size_t                index;
596
597
0
    index = 0;
598
599
0
    cfl_list_foreach(iterator, &map->label_keys) {
600
0
        label = cfl_list_entry(iterator, struct cmt_map_label, _head);
601
602
0
        if (label_index == index) {
603
0
            cmt_map_label_destroy(label);
604
605
0
            return FLB_TRUE;
606
0
        }
607
608
0
        index++;
609
0
    }
610
611
0
    return FLB_FALSE;
612
0
}
613
614
int metrics_data_point_remove_label_value(struct cmt_metric *metric,
615
                                          size_t label_index)
616
0
{
617
0
    struct cfl_list      *iterator;
618
0
    struct cmt_map_label *label;
619
0
    size_t                index;
620
621
0
    index = 0;
622
623
0
    cfl_list_foreach(iterator, &metric->labels) {
624
0
        label = cfl_list_entry(iterator, struct cmt_map_label, _head);
625
626
0
        if (label_index == index) {
627
0
            cmt_map_label_destroy(label);
628
629
0
            return FLB_TRUE;
630
0
        }
631
632
0
        index++;
633
0
    }
634
635
0
    return FLB_FALSE;
636
0
}
637
638
int metrics_data_point_transform_label_value(struct cmt_metric *metric,
639
                                             size_t label_index,
640
                                             label_transformer transformer)
641
0
{
642
0
    struct cfl_list      *iterator;
643
0
    struct cmt_map_label *label;
644
0
    size_t                index;
645
646
0
    index = 0;
647
648
0
    cfl_list_foreach(iterator, &metric->labels) {
649
0
        label = cfl_list_entry(iterator, struct cmt_map_label, _head);
650
651
0
        if (label_index == index) {
652
0
            return transformer(metric, &label->name);
653
0
        }
654
655
0
        index++;
656
0
    }
657
658
0
    return FLB_FALSE;
659
0
}
660
661
int metrics_data_point_set_label_value(struct cmt_metric *metric,
662
                                       size_t label_index,
663
                                       char *label_value,
664
                                       int overwrite,
665
                                       int insert)
666
0
{
667
0
    struct cmt_map_label *new_label;
668
0
    struct cfl_list      *iterator;
669
0
    cfl_sds_t             result;
670
0
    size_t                index;
671
0
    struct cmt_map_label *label;
672
673
0
    label = NULL;
674
0
    index = 0;
675
676
0
    cfl_list_foreach(iterator, &metric->labels) {
677
0
        label = cfl_list_entry(iterator, struct cmt_map_label, _head);
678
679
0
        if (label_index == index) {
680
0
            break;
681
0
        }
682
683
0
        index++;
684
0
    }
685
686
0
    if (label_index != index) {
687
0
        return FLB_FALSE;
688
0
    }
689
690
0
    if (insert == FLB_TRUE) {
691
0
        new_label = cmt_map_label_create(label_value);
692
693
0
        if (new_label == NULL) {
694
0
            return FLB_FALSE;
695
0
        }
696
697
0
        if (label != NULL) {
698
0
            cfl_list_add_after(&new_label->_head,
699
0
                               &label->_head,
700
0
                               &metric->labels);
701
0
        }
702
0
        else {
703
0
            cfl_list_append(&new_label->_head,
704
0
                            &metric->labels);
705
0
        }
706
0
    }
707
0
    else {
708
0
        if (label == NULL) {
709
0
            return FLB_FALSE;
710
0
        }
711
712
0
        if (label->name == NULL) {
713
0
            label->name = cfl_sds_create(label_value);
714
715
0
            if (label->name == NULL) {
716
0
                return FLB_FALSE;
717
0
            }
718
0
        }
719
0
        else {
720
0
            if (overwrite == FLB_TRUE ||
721
0
                cfl_sds_len(label->name) == 0) {
722
0
                cfl_sds_set_len(label->name, 0);
723
724
0
                result = cfl_sds_cat(label->name,
725
0
                                     label_value,
726
0
                                     strlen(label_value));
727
728
0
                if (result == NULL) {
729
0
                    return FLB_FALSE;
730
0
                }
731
732
0
                label->name = result;
733
0
            }
734
0
        }
735
0
    }
736
737
0
    return FLB_TRUE;
738
0
}
739
740
741
int metrics_map_convert_static_metric(struct cmt_map *map,
742
                                      size_t label_index,
743
                                      char *label_value)
744
0
{
745
0
    struct cmt_metric *metric;
746
0
    int                result;
747
0
    size_t             index;
748
0
    cfl_hash_state_t   state;
749
0
    uint64_t           hash;
750
751
0
    cfl_hash_64bits_reset(&state);
752
753
0
    cfl_hash_64bits_update(&state,
754
0
                           map->opts->fqname,
755
0
                           cfl_sds_len(map->opts->fqname));
756
757
0
    for (index = 0 ; index < map->label_count ; index++) {
758
0
        if (index != label_index) {
759
0
            cfl_hash_64bits_update(&state,
760
0
                                   "_NULL_",
761
0
                                   6);
762
0
        }
763
0
        else {
764
0
            cfl_hash_64bits_update(&state,
765
0
                                   label_value,
766
0
                                   strlen(label_value));
767
0
        }
768
0
    }
769
770
0
    hash = cfl_hash_64bits_digest(&state);
771
772
0
    metric = map_metric_create(hash, 0, NULL);
773
774
0
    if (metric == NULL) {
775
0
        return FLB_FALSE;
776
0
    }
777
778
0
    for (index = 0 ; index < map->label_count ; index++) {
779
0
        if (index != label_index) {
780
0
            result = metrics_data_point_set_label_value(metric,
781
0
                                                        index,
782
0
                                                        "",
783
0
                                                        FLB_TRUE,
784
0
                                                        FLB_TRUE);
785
0
        }
786
0
        else {
787
0
            result = metrics_data_point_set_label_value(metric,
788
0
                                                        index,
789
0
                                                        label_value,
790
0
                                                        FLB_TRUE,
791
0
                                                        FLB_TRUE);
792
0
        }
793
794
0
        if (result != FLB_TRUE) {
795
0
            map_metric_destroy(metric);
796
797
0
            return FLB_FALSE;
798
0
        }
799
0
    }
800
801
0
    metric->val = map->metric.val;
802
803
0
    metric->hist_buckets = map->metric.hist_buckets;
804
0
    metric->hist_count = map->metric.hist_count;
805
0
    metric->hist_sum = map->metric.hist_sum;
806
807
0
    metric->sum_quantiles_set = map->metric.sum_quantiles_set;
808
0
    metric->sum_quantiles = map->metric.sum_quantiles;
809
0
    metric->sum_quantiles_count = map->metric.sum_quantiles_count;
810
0
    metric->sum_count = map->metric.sum_count;
811
0
    metric->sum_sum = map->metric.sum_sum;
812
813
0
    metric->timestamp = map->metric.timestamp;
814
815
0
    map->metric_static_set = 0;
816
817
0
    cfl_list_add(&metric->_head, &map->metrics);
818
819
0
    memset(&map->metric, 0, sizeof(struct cmt_metric));
820
821
0
    return FLB_TRUE;
822
0
}
823
824
int metrics_map_remove_label_value(struct cmt_map *map,
825
                                   size_t label_index)
826
0
{
827
0
    struct cfl_list   *iterator;
828
0
    struct cmt_metric *metric;
829
0
    int                result;
830
831
0
    result = FLB_TRUE;
832
833
0
    cfl_list_foreach(iterator, &map->metrics) {
834
0
        metric = cfl_list_entry(iterator, struct cmt_metric, _head);
835
836
0
        result = metrics_data_point_remove_label_value(metric, label_index);
837
838
0
        if (result == FLB_FALSE) {
839
0
            break;
840
0
        }
841
0
    }
842
843
0
    return result;
844
0
}
845
846
int metrics_map_set_label_value(struct cmt_map *map,
847
                                size_t label_index,
848
                                char *label_value,
849
                                int overwrite,
850
                                int insert)
851
0
{
852
0
    struct cfl_list   *iterator;
853
0
    struct cmt_metric *metric;
854
0
    int                result;
855
856
0
    result = FLB_TRUE;
857
858
0
    cfl_list_foreach(iterator, &map->metrics) {
859
0
        metric = cfl_list_entry(iterator, struct cmt_metric, _head);
860
861
0
        result = metrics_data_point_set_label_value(metric,
862
0
                                                    label_index,
863
0
                                                    label_value,
864
0
                                                    overwrite,
865
0
                                                    insert);
866
867
0
        if (result == FLB_FALSE) {
868
0
            break;
869
0
        }
870
0
    }
871
872
0
#ifdef PROMOTE_STATIC_METRICS_ON_LABEL_INSERT
873
0
    if (map->metric_static_set == 1) {
874
0
        result = metrics_map_convert_static_metric(map,
875
0
                                                   label_index,
876
0
                                                   label_value);
877
878
0
        if(result == FLB_FALSE) {
879
0
            return FLB_FALSE;
880
0
        }
881
0
    }
882
0
#endif
883
884
0
    return result;
885
0
}
886
887
int metrics_map_transform_label_value(struct cmt_map *map,
888
                                      size_t label_index,
889
                                      label_transformer transformer)
890
0
{
891
0
    struct cfl_list   *iterator;
892
0
    struct cmt_metric *metric;
893
0
    int                result;
894
895
0
    result = FLB_TRUE;
896
897
0
    cfl_list_foreach(iterator, &map->metrics) {
898
0
        metric = cfl_list_entry(iterator, struct cmt_metric, _head);
899
900
0
        result = metrics_data_point_transform_label_value(metric,
901
0
                                                          label_index,
902
0
                                                          transformer);
903
904
0
        if (result == FLB_FALSE) {
905
0
            break;
906
0
        }
907
0
    }
908
909
0
    return result;
910
0
}
911
912
int metrics_map_update_label(struct cmt_map *map,
913
                             char *label_name,
914
                             char *label_value)
915
0
{
916
0
    ssize_t label_index;
917
0
    int     result;
918
919
0
    label_index = metrics_map_get_label_index(map, label_name);
920
921
0
    if (label_index == -1) {
922
0
        return FLB_TRUE;
923
0
    }
924
925
0
    result = metrics_map_set_label_value(map,
926
0
                                         label_index,
927
0
                                         label_value,
928
0
                                         FLB_TRUE,
929
0
                                         FLB_FALSE);
930
931
0
    if(result == FLB_FALSE) {
932
0
        return FLB_FALSE;
933
0
    }
934
935
0
    return FLB_TRUE;
936
0
}
937
938
int metrics_map_transform_label(struct cmt_map *map,
939
                                char *label_name,
940
                                label_transformer transformer)
941
0
{
942
0
    ssize_t label_index;
943
0
    int     result;
944
945
0
    label_index = metrics_map_get_label_index(map, label_name);
946
947
0
    if (label_index == -1) {
948
0
        return FLB_TRUE;
949
0
    }
950
951
0
    result = metrics_map_transform_label_value(map,
952
0
                                               label_index,
953
0
                                               transformer);
954
955
0
    if(result == FLB_FALSE) {
956
0
        return FLB_FALSE;
957
0
    }
958
959
0
    return FLB_TRUE;
960
0
}
961
962
int metrics_map_insert_label(struct cmt_map *map,
963
                             char *label_name,
964
                             char *label_value)
965
0
{
966
0
    ssize_t label_index;
967
0
    int     label_added;
968
0
    int     result;
969
970
0
    label_added = FLB_FALSE;
971
0
    label_index = metrics_map_get_label_index(map, label_name);
972
973
0
    if (label_index == -1) {
974
0
        label_index = metrics_map_insert_label_name(map, label_name);
975
0
        label_added = FLB_TRUE;
976
0
    }
977
978
0
    if (label_index == -1) {
979
0
        return FLB_FALSE;
980
0
    }
981
982
0
    result = metrics_map_set_label_value(map,
983
0
                                         label_index,
984
0
                                         label_value,
985
0
                                         FLB_FALSE,
986
0
                                         label_added);
987
988
0
    if(result == FLB_FALSE) {
989
0
        return FLB_FALSE;
990
0
    }
991
992
0
    return FLB_TRUE;
993
0
}
994
995
int metrics_map_upsert_label(struct cmt_map *map,
996
                             char *label_name,
997
                             char *label_value)
998
0
{
999
0
    ssize_t label_index;
1000
0
    int     label_added;
1001
0
    int     result;
1002
1003
0
    label_added = FLB_FALSE;
1004
0
    label_index = metrics_map_get_label_index(map, label_name);
1005
1006
0
    if (label_index == -1) {
1007
0
        label_index = metrics_map_insert_label_name(map, label_name);
1008
0
        label_added = FLB_TRUE;
1009
0
    }
1010
1011
0
    if (label_index == -1) {
1012
0
        return FLB_FALSE;
1013
0
    }
1014
1015
0
    result = metrics_map_set_label_value(map,
1016
0
                                         label_index,
1017
0
                                         label_value,
1018
0
                                         FLB_TRUE,
1019
0
                                         label_added);
1020
1021
0
    if(result == FLB_FALSE) {
1022
0
        return FLB_FALSE;
1023
0
    }
1024
1025
0
    return FLB_TRUE;
1026
0
}
1027
1028
int metrics_map_remove_label(struct cmt_map *map,
1029
                             char *label_name)
1030
0
{
1031
0
    ssize_t label_index;
1032
0
    int     result;
1033
1034
0
    label_index = metrics_map_get_label_index(map, label_name);
1035
1036
0
    if (label_index == -1) {
1037
0
        return FLB_TRUE;
1038
0
    }
1039
1040
0
    map->label_count--;
1041
1042
0
    result = metrics_map_remove_label_name(map, label_index);
1043
1044
0
    if(result == FLB_TRUE) {
1045
0
        result = metrics_map_remove_label_value(map, label_index);
1046
0
    }
1047
1048
0
    return result;
1049
0
}
1050
1051
static int metrics_context_contains_dynamic_label(struct cmt *metrics_context,
1052
                                                  char *label_name)
1053
0
{
1054
0
    struct cfl_list      *metric_iterator;
1055
0
    struct cmt_histogram *histogram;
1056
0
    struct cmt_summary   *summary;
1057
0
    struct cmt_untyped   *untyped;
1058
0
    struct cmt_counter   *counter;
1059
0
    struct cmt_gauge     *gauge;
1060
1061
0
    cfl_list_foreach(metric_iterator, &metrics_context->histograms) {
1062
0
        histogram = cfl_list_entry(metric_iterator, struct cmt_histogram, _head);
1063
1064
0
        if(metrics_map_contains_label(histogram->map, label_name) == FLB_TRUE) {
1065
0
            return FLB_TRUE;
1066
0
        }
1067
0
    }
1068
1069
0
    cfl_list_foreach(metric_iterator, &metrics_context->summaries) {
1070
0
        summary = cfl_list_entry(metric_iterator, struct cmt_summary, _head);
1071
1072
0
        if(metrics_map_contains_label(summary->map, label_name) == FLB_TRUE) {
1073
0
            return FLB_TRUE;
1074
0
        }
1075
0
    }
1076
1077
0
    cfl_list_foreach(metric_iterator, &metrics_context->untypeds) {
1078
0
        untyped = cfl_list_entry(metric_iterator, struct cmt_untyped, _head);
1079
1080
0
        if(metrics_map_contains_label(untyped->map, label_name) == FLB_TRUE) {
1081
0
            return FLB_TRUE;
1082
0
        }
1083
0
    }
1084
1085
0
    cfl_list_foreach(metric_iterator, &metrics_context->counters) {
1086
0
        counter = cfl_list_entry(metric_iterator, struct cmt_counter, _head);
1087
1088
0
        if(metrics_map_contains_label(counter->map, label_name) == FLB_TRUE) {
1089
0
            return FLB_TRUE;
1090
0
        }
1091
0
    }
1092
1093
0
    cfl_list_foreach(metric_iterator, &metrics_context->gauges) {
1094
0
        gauge = cfl_list_entry(metric_iterator, struct cmt_gauge, _head);
1095
1096
0
        if(metrics_map_contains_label(gauge->map, label_name) == FLB_TRUE) {
1097
0
            return FLB_TRUE;
1098
0
        }
1099
0
    }
1100
1101
0
    return FLB_FALSE;
1102
0
}
1103
1104
static int metrics_context_insert_dynamic_label(struct cmt *metrics_context,
1105
                                                char *label_name,
1106
                                                char *label_value)
1107
0
{
1108
0
    struct cfl_list      *metric_iterator;
1109
0
    struct cmt_histogram *histogram;
1110
0
    struct cmt_summary   *summary;
1111
0
    struct cmt_untyped   *untyped;
1112
0
    struct cmt_counter   *counter;
1113
0
    int                   result;
1114
0
    struct cmt_gauge     *gauge;
1115
1116
0
    cfl_list_foreach(metric_iterator, &metrics_context->histograms) {
1117
0
        histogram = cfl_list_entry(metric_iterator, struct cmt_histogram, _head);
1118
1119
0
        result = metrics_map_insert_label(histogram->map,
1120
0
                                          label_name,
1121
0
                                          label_value);
1122
1123
0
        if (result == FLB_FALSE) {
1124
0
            return FLB_FALSE;
1125
0
        }
1126
0
    }
1127
1128
0
    cfl_list_foreach(metric_iterator, &metrics_context->summaries) {
1129
0
        summary = cfl_list_entry(metric_iterator, struct cmt_summary, _head);
1130
1131
0
        result = metrics_map_insert_label(summary->map,
1132
0
                                          label_name,
1133
0
                                          label_value);
1134
1135
0
        if (result == FLB_FALSE) {
1136
0
            return FLB_FALSE;
1137
0
        }
1138
0
    }
1139
1140
0
    cfl_list_foreach(metric_iterator, &metrics_context->untypeds) {
1141
0
        untyped = cfl_list_entry(metric_iterator, struct cmt_untyped, _head);
1142
1143
0
        result = metrics_map_insert_label(untyped->map,
1144
0
                                          label_name,
1145
0
                                          label_value);
1146
1147
0
        if (result == FLB_FALSE) {
1148
0
            return FLB_FALSE;
1149
0
        }
1150
0
    }
1151
1152
0
    cfl_list_foreach(metric_iterator, &metrics_context->counters) {
1153
0
        counter = cfl_list_entry(metric_iterator, struct cmt_counter, _head);
1154
1155
0
        result = metrics_map_insert_label(counter->map,
1156
0
                                          label_name,
1157
0
                                          label_value);
1158
1159
0
        if (result == FLB_FALSE) {
1160
0
            return FLB_FALSE;
1161
0
        }
1162
0
    }
1163
1164
0
    cfl_list_foreach(metric_iterator, &metrics_context->gauges) {
1165
0
        gauge = cfl_list_entry(metric_iterator, struct cmt_gauge, _head);
1166
1167
0
        result = metrics_map_insert_label(gauge->map,
1168
0
                                          label_name,
1169
0
                                          label_value);
1170
1171
0
        if (result == FLB_FALSE) {
1172
0
            return FLB_FALSE;
1173
0
        }
1174
0
    }
1175
1176
0
    return FLB_TRUE;
1177
0
}
1178
1179
static int metrics_context_update_dynamic_label(struct cmt *metrics_context,
1180
                                                char *label_name,
1181
                                                char *label_value)
1182
0
{
1183
0
    struct cfl_list      *metric_iterator;
1184
0
    struct cmt_histogram *histogram;
1185
0
    struct cmt_summary   *summary;
1186
0
    struct cmt_untyped   *untyped;
1187
0
    struct cmt_counter   *counter;
1188
0
    int                   result;
1189
0
    struct cmt_gauge     *gauge;
1190
1191
0
    cfl_list_foreach(metric_iterator, &metrics_context->histograms) {
1192
0
        histogram = cfl_list_entry(metric_iterator, struct cmt_histogram, _head);
1193
1194
0
        result = metrics_map_update_label(histogram->map,
1195
0
                                          label_name,
1196
0
                                          label_value);
1197
1198
0
        if (result == FLB_FALSE) {
1199
0
            return FLB_FALSE;
1200
0
        }
1201
0
    }
1202
1203
0
    cfl_list_foreach(metric_iterator, &metrics_context->summaries) {
1204
0
        summary = cfl_list_entry(metric_iterator, struct cmt_summary, _head);
1205
1206
0
        result = metrics_map_update_label(summary->map,
1207
0
                                          label_name,
1208
0
                                          label_value);
1209
1210
0
        if (result == FLB_FALSE) {
1211
0
            return FLB_FALSE;
1212
0
        }
1213
0
    }
1214
1215
0
    cfl_list_foreach(metric_iterator, &metrics_context->untypeds) {
1216
0
        untyped = cfl_list_entry(metric_iterator, struct cmt_untyped, _head);
1217
1218
0
        result = metrics_map_update_label(untyped->map,
1219
0
                                          label_name,
1220
0
                                          label_value);
1221
1222
0
        if (result == FLB_FALSE) {
1223
0
            return FLB_FALSE;
1224
0
        }
1225
0
    }
1226
1227
0
    cfl_list_foreach(metric_iterator, &metrics_context->counters) {
1228
0
        counter = cfl_list_entry(metric_iterator, struct cmt_counter, _head);
1229
1230
0
        result = metrics_map_update_label(counter->map,
1231
0
                                          label_name,
1232
0
                                          label_value);
1233
1234
0
        if (result == FLB_FALSE) {
1235
0
            return FLB_FALSE;
1236
0
        }
1237
0
    }
1238
1239
0
    cfl_list_foreach(metric_iterator, &metrics_context->gauges) {
1240
0
        gauge = cfl_list_entry(metric_iterator, struct cmt_gauge, _head);
1241
1242
0
        result = metrics_map_update_label(gauge->map,
1243
0
                                          label_name,
1244
0
                                          label_value);
1245
1246
0
        if (result == FLB_FALSE) {
1247
0
            return FLB_FALSE;
1248
0
        }
1249
0
    }
1250
1251
0
    return FLB_TRUE;
1252
0
}
1253
1254
static int metrics_context_transform_dynamic_label(struct cmt *metrics_context,
1255
                                                   char *label_name,
1256
                                                   label_transformer transformer)
1257
0
{
1258
0
    struct cfl_list      *metric_iterator;
1259
0
    struct cmt_histogram *histogram;
1260
0
    struct cmt_summary   *summary;
1261
0
    struct cmt_untyped   *untyped;
1262
0
    struct cmt_counter   *counter;
1263
0
    int                   result;
1264
0
    struct cmt_gauge     *gauge;
1265
1266
0
    cfl_list_foreach(metric_iterator, &metrics_context->histograms) {
1267
0
        histogram = cfl_list_entry(metric_iterator, struct cmt_histogram, _head);
1268
1269
0
        result = metrics_map_transform_label(histogram->map,
1270
0
                                             label_name,
1271
0
                                             transformer);
1272
1273
0
        if (result == FLB_FALSE) {
1274
0
            return FLB_FALSE;
1275
0
        }
1276
0
    }
1277
1278
0
    cfl_list_foreach(metric_iterator, &metrics_context->summaries) {
1279
0
        summary = cfl_list_entry(metric_iterator, struct cmt_summary, _head);
1280
1281
0
        result = metrics_map_transform_label(summary->map,
1282
0
                                             label_name,
1283
0
                                             transformer);
1284
1285
0
        if (result == FLB_FALSE) {
1286
0
            return FLB_FALSE;
1287
0
        }
1288
0
    }
1289
1290
0
    cfl_list_foreach(metric_iterator, &metrics_context->untypeds) {
1291
0
        untyped = cfl_list_entry(metric_iterator, struct cmt_untyped, _head);
1292
1293
0
        result = metrics_map_transform_label(untyped->map,
1294
0
                                             label_name,
1295
0
                                             transformer);
1296
1297
0
        if (result == FLB_FALSE) {
1298
0
            return FLB_FALSE;
1299
0
        }
1300
0
    }
1301
1302
0
    cfl_list_foreach(metric_iterator, &metrics_context->counters) {
1303
0
        counter = cfl_list_entry(metric_iterator, struct cmt_counter, _head);
1304
1305
0
        result = metrics_map_transform_label(counter->map,
1306
0
                                             label_name,
1307
0
                                             transformer);
1308
1309
0
        if (result == FLB_FALSE) {
1310
0
            return FLB_FALSE;
1311
0
        }
1312
0
    }
1313
1314
0
    cfl_list_foreach(metric_iterator, &metrics_context->gauges) {
1315
0
        gauge = cfl_list_entry(metric_iterator, struct cmt_gauge, _head);
1316
1317
0
        result = metrics_map_transform_label(gauge->map,
1318
0
                                             label_name,
1319
0
                                             transformer);
1320
1321
0
        if (result == FLB_FALSE) {
1322
0
            return FLB_FALSE;
1323
0
        }
1324
0
    }
1325
1326
0
    return FLB_TRUE;
1327
0
}
1328
1329
static int metrics_context_upsert_dynamic_label(struct cmt *metrics_context,
1330
                                                char *label_name,
1331
                                                char *label_value)
1332
0
{
1333
0
    struct cfl_list      *metric_iterator;
1334
0
    struct cmt_histogram *histogram;
1335
0
    struct cmt_summary   *summary;
1336
0
    struct cmt_untyped   *untyped;
1337
0
    struct cmt_counter   *counter;
1338
0
    int                   result;
1339
0
    struct cmt_gauge     *gauge;
1340
1341
0
    cfl_list_foreach(metric_iterator, &metrics_context->histograms) {
1342
0
        histogram = cfl_list_entry(metric_iterator, struct cmt_histogram, _head);
1343
1344
0
        result = metrics_map_upsert_label(histogram->map,
1345
0
                                          label_name,
1346
0
                                          label_value);
1347
1348
0
        if (result == FLB_FALSE) {
1349
0
            return FLB_FALSE;
1350
0
        }
1351
0
    }
1352
1353
0
    cfl_list_foreach(metric_iterator, &metrics_context->summaries) {
1354
0
        summary = cfl_list_entry(metric_iterator, struct cmt_summary, _head);
1355
1356
0
        result = metrics_map_upsert_label(summary->map,
1357
0
                                          label_name,
1358
0
                                          label_value);
1359
1360
0
        if (result == FLB_FALSE) {
1361
0
            return FLB_FALSE;
1362
0
        }
1363
0
    }
1364
1365
0
    cfl_list_foreach(metric_iterator, &metrics_context->untypeds) {
1366
0
        untyped = cfl_list_entry(metric_iterator, struct cmt_untyped, _head);
1367
1368
0
        result = metrics_map_upsert_label(untyped->map,
1369
0
                                          label_name,
1370
0
                                          label_value);
1371
1372
0
        if (result == FLB_FALSE) {
1373
0
            return FLB_FALSE;
1374
0
        }
1375
0
    }
1376
1377
0
    cfl_list_foreach(metric_iterator, &metrics_context->counters) {
1378
0
        counter = cfl_list_entry(metric_iterator, struct cmt_counter, _head);
1379
1380
0
        result = metrics_map_upsert_label(counter->map,
1381
0
                                          label_name,
1382
0
                                          label_value);
1383
1384
0
        if (result == FLB_FALSE) {
1385
0
            return FLB_FALSE;
1386
0
        }
1387
0
    }
1388
1389
0
    cfl_list_foreach(metric_iterator, &metrics_context->gauges) {
1390
0
        gauge = cfl_list_entry(metric_iterator, struct cmt_gauge, _head);
1391
1392
0
        result = metrics_map_upsert_label(gauge->map,
1393
0
                                          label_name,
1394
0
                                          label_value);
1395
1396
0
        if (result == FLB_FALSE) {
1397
0
            return FLB_FALSE;
1398
0
        }
1399
0
    }
1400
1401
0
    return FLB_TRUE;
1402
0
}
1403
1404
static int metrics_context_remove_dynamic_label(struct cmt *metrics_context,
1405
                                                char *label_name)
1406
0
{
1407
0
    struct cfl_list      *metric_iterator;
1408
0
    struct cmt_histogram *histogram;
1409
0
    struct cmt_summary   *summary;
1410
0
    struct cmt_untyped   *untyped;
1411
0
    struct cmt_counter   *counter;
1412
0
    int                   result;
1413
0
    struct cmt_gauge     *gauge;
1414
1415
0
    cfl_list_foreach(metric_iterator, &metrics_context->histograms) {
1416
0
        histogram = cfl_list_entry(metric_iterator, struct cmt_histogram, _head);
1417
1418
0
        result = metrics_map_remove_label(histogram->map,
1419
0
                                          label_name);
1420
1421
0
        if (result == FLB_FALSE) {
1422
0
            return FLB_FALSE;
1423
0
        }
1424
0
    }
1425
1426
0
    cfl_list_foreach(metric_iterator, &metrics_context->summaries) {
1427
0
        summary = cfl_list_entry(metric_iterator, struct cmt_summary, _head);
1428
1429
0
        result = metrics_map_remove_label(summary->map,
1430
0
                                          label_name);
1431
1432
0
        if (result == FLB_FALSE) {
1433
0
            return FLB_FALSE;
1434
0
        }
1435
0
    }
1436
1437
0
    cfl_list_foreach(metric_iterator, &metrics_context->untypeds) {
1438
0
        untyped = cfl_list_entry(metric_iterator, struct cmt_untyped, _head);
1439
1440
0
        result = metrics_map_remove_label(untyped->map,
1441
0
                                          label_name);
1442
1443
0
        if (result == FLB_FALSE) {
1444
0
            return FLB_FALSE;
1445
0
        }
1446
0
    }
1447
1448
0
    cfl_list_foreach(metric_iterator, &metrics_context->counters) {
1449
0
        counter = cfl_list_entry(metric_iterator, struct cmt_counter, _head);
1450
1451
0
        result = metrics_map_remove_label(counter->map,
1452
0
                                          label_name);
1453
1454
0
        if (result == FLB_FALSE) {
1455
0
            return FLB_FALSE;
1456
0
        }
1457
0
    }
1458
1459
0
    cfl_list_foreach(metric_iterator, &metrics_context->gauges) {
1460
0
        gauge = cfl_list_entry(metric_iterator, struct cmt_gauge, _head);
1461
1462
0
        result = metrics_map_remove_label(gauge->map,
1463
0
                                          label_name);
1464
1465
0
        if (result == FLB_FALSE) {
1466
0
            return FLB_FALSE;
1467
0
        }
1468
0
    }
1469
1470
0
    return FLB_TRUE;
1471
0
}
1472
1473
static int update_labels(struct cmt *metrics_context,
1474
                         struct cfl_list *labels)
1475
0
{
1476
0
    struct cfl_list *iterator;
1477
0
    int              result;
1478
0
    struct cfl_kv   *pair;
1479
1480
0
    cfl_list_foreach(iterator, labels) {
1481
0
        pair = cfl_list_entry(iterator, struct cfl_kv, _head);
1482
1483
0
        result = metrics_context_contains_dynamic_label(metrics_context,
1484
0
                                                        pair->key);
1485
1486
0
        if (result == FLB_TRUE) {
1487
0
            result = metrics_context_update_dynamic_label(metrics_context,
1488
0
                                                          pair->key,
1489
0
                                                          pair->val);
1490
1491
0
            if (result == FLB_FALSE) {
1492
0
                return FLB_FALSE;
1493
0
            }
1494
0
        }
1495
1496
0
        result = metrics_context_contains_static_label(metrics_context,
1497
0
                                                       pair->key);
1498
1499
0
        if (result == FLB_TRUE) {
1500
0
            result = metrics_context_update_static_label(metrics_context,
1501
0
                                                         pair->key,
1502
0
                                                         pair->val);
1503
1504
0
            if (result == FLB_FALSE) {
1505
0
                return FLB_FALSE;
1506
0
            }
1507
0
        }
1508
0
    }
1509
1510
0
    return FLB_PROCESSOR_SUCCESS;
1511
0
}
1512
1513
static int insert_labels(struct cmt *metrics_context,
1514
                         struct cfl_list *labels)
1515
0
{
1516
0
    struct cfl_list *iterator;
1517
0
    int              result;
1518
0
    struct cfl_kv   *pair;
1519
1520
0
    cfl_list_foreach(iterator, labels) {
1521
0
        pair = cfl_list_entry(iterator, struct cfl_kv, _head);
1522
1523
0
        result = metrics_context_contains_dynamic_label(metrics_context,
1524
0
                                                        pair->key);
1525
1526
0
        if (result == FLB_TRUE) {
1527
0
            continue;
1528
0
        }
1529
1530
0
        result = metrics_context_insert_dynamic_label(metrics_context,
1531
0
                                                      pair->key,
1532
0
                                                      pair->val);
1533
1534
0
        if (result == FLB_FALSE) {
1535
0
            return FLB_FALSE;
1536
0
        }
1537
1538
0
        result = metrics_context_contains_static_label(metrics_context,
1539
0
                                                       pair->key);
1540
1541
0
        if (result == FLB_TRUE) {
1542
0
            result = metrics_context_insert_static_label(metrics_context,
1543
0
                                                         pair->key,
1544
0
                                                         pair->val);
1545
1546
0
            if (result == FLB_FALSE) {
1547
0
                return FLB_FALSE;
1548
0
            }
1549
0
        }
1550
0
    }
1551
1552
0
    return FLB_PROCESSOR_SUCCESS;
1553
0
}
1554
1555
static int upsert_labels(struct cmt *metrics_context,
1556
                         struct cfl_list *labels)
1557
0
{
1558
0
    struct cfl_list *iterator;
1559
0
    int              result;
1560
0
    struct cfl_kv   *pair;
1561
1562
0
    cfl_list_foreach(iterator, labels) {
1563
0
        pair = cfl_list_entry(iterator, struct cfl_kv, _head);
1564
1565
0
        result = metrics_context_contains_dynamic_label(metrics_context,
1566
0
                                                        pair->key);
1567
1568
0
        if (result == FLB_TRUE) {
1569
0
            result = metrics_context_upsert_dynamic_label(metrics_context,
1570
0
                                                          pair->key,
1571
0
                                                          pair->val);
1572
1573
0
            if (result == FLB_FALSE) {
1574
0
                return FLB_FALSE;
1575
0
            }
1576
0
        }
1577
0
        else {
1578
0
            result = metrics_context_upsert_static_label(metrics_context,
1579
0
                                                         pair->key,
1580
0
                                                         pair->val);
1581
1582
0
            if (result == FLB_FALSE) {
1583
0
                return FLB_FALSE;
1584
0
            }
1585
0
        }
1586
0
    }
1587
1588
0
    return FLB_PROCESSOR_SUCCESS;
1589
0
}
1590
1591
static int delete_labels(struct cmt *metrics_context,
1592
                         struct mk_list *labels)
1593
0
{
1594
0
    struct mk_list         *iterator;
1595
0
    int                     result;
1596
0
    struct flb_slist_entry *entry;
1597
1598
0
    mk_list_foreach(iterator, labels) {
1599
0
        entry = mk_list_entry(iterator, struct flb_slist_entry, _head);
1600
1601
0
        result = metrics_context_contains_dynamic_label(metrics_context,
1602
0
                                                        entry->str);
1603
1604
0
        if (result == FLB_TRUE) {
1605
0
            result = metrics_context_remove_dynamic_label(metrics_context,
1606
0
                                                          entry->str);
1607
1608
0
            if (result == FLB_FALSE) {
1609
0
                return FLB_FALSE;
1610
0
            }
1611
0
        }
1612
0
        else {
1613
0
            result = metrics_context_contains_static_label(metrics_context,
1614
0
                                                           entry->str);
1615
1616
0
            if (result == FLB_TRUE) {
1617
0
                result = metrics_context_remove_static_label(metrics_context,
1618
0
                                                             entry->str);
1619
1620
0
                if (result == FLB_FALSE) {
1621
0
                    return FLB_FALSE;
1622
0
                }
1623
0
            }
1624
0
        }
1625
0
    }
1626
1627
0
    return FLB_PROCESSOR_SUCCESS;
1628
0
}
1629
1630
static int hash_transformer(struct cmt_metric *metric, cfl_sds_t *value)
1631
0
{
1632
0
    unsigned char digest_buffer[32];
1633
0
    int           result;
1634
1635
0
    if (value == NULL) {
1636
0
        return FLB_FALSE;
1637
0
    }
1638
1639
0
    if (cfl_sds_len(*value) == 0) {
1640
0
        return FLB_TRUE;
1641
0
    }
1642
1643
0
    result = flb_hash_simple(FLB_HASH_SHA256,
1644
0
                             (unsigned char *) *value,
1645
0
                             cfl_sds_len(*value),
1646
0
                             digest_buffer,
1647
0
                             sizeof(digest_buffer));
1648
1649
0
    if (result != FLB_CRYPTO_SUCCESS) {
1650
0
        return FLB_FALSE;
1651
0
    }
1652
1653
0
    return hex_encode(digest_buffer, sizeof(digest_buffer), value);
1654
0
}
1655
1656
static int hash_labels(struct cmt *metrics_context,
1657
                       struct mk_list *labels)
1658
0
{
1659
0
    struct mk_list         *iterator;
1660
0
    int                     result;
1661
0
    struct flb_slist_entry *entry;
1662
1663
0
    mk_list_foreach(iterator, labels) {
1664
0
        entry = mk_list_entry(iterator, struct flb_slist_entry, _head);
1665
1666
0
        result = metrics_context_contains_dynamic_label(metrics_context,
1667
0
                                                        entry->str);
1668
1669
0
        if (result == FLB_TRUE) {
1670
0
            result = metrics_context_transform_dynamic_label(metrics_context,
1671
0
                                                             entry->str,
1672
0
                                                             hash_transformer);
1673
1674
0
            if (result == FLB_FALSE) {
1675
0
                return FLB_FALSE;
1676
0
            }
1677
0
        }
1678
0
        else {
1679
0
            result = metrics_context_contains_static_label(metrics_context,
1680
0
                                                           entry->str);
1681
1682
0
            if (result == FLB_TRUE) {
1683
0
                result = metrics_context_transform_static_label(metrics_context,
1684
0
                                                                entry->str,
1685
0
                                                                hash_transformer);
1686
1687
0
                if (result == FLB_FALSE) {
1688
0
                    return FLB_FALSE;
1689
0
                }
1690
0
            }
1691
0
        }
1692
0
    }
1693
1694
0
    return FLB_PROCESSOR_SUCCESS;
1695
0
}
1696
1697
static int cb_process_metrics(struct flb_processor_instance *processor_instance,
1698
                              struct cmt *metrics_context,
1699
                              struct cmt **out_context,
1700
                              const char *tag,
1701
                              int tag_len)
1702
0
{
1703
0
    struct cmt                        *out_cmt;
1704
0
    struct internal_processor_context *processor_context;
1705
0
    int                                result;
1706
1707
0
    processor_context =
1708
0
        (struct internal_processor_context *) processor_instance->context;
1709
1710
0
    out_cmt = cmt_create();
1711
0
    if (out_cmt == NULL) {
1712
0
        flb_plg_error(processor_instance, "could not create out_cmt context");
1713
0
        return FLB_PROCESSOR_FAILURE;
1714
0
    }
1715
1716
0
    result = cmt_cat(out_cmt, metrics_context);
1717
0
    if (result != 0) {
1718
0
        cmt_destroy(out_cmt);
1719
1720
0
        return FLB_PROCESSOR_FAILURE;
1721
0
    }
1722
1723
0
    result = delete_labels(out_cmt,
1724
0
                           &processor_context->delete_labels);
1725
1726
0
    if (result == FLB_PROCESSOR_SUCCESS) {
1727
0
        result = update_labels(out_cmt,
1728
0
                               &processor_context->update_labels);
1729
0
    }
1730
1731
0
    if (result == FLB_PROCESSOR_SUCCESS) {
1732
0
        result = upsert_labels(out_cmt,
1733
0
                               &processor_context->upsert_labels);
1734
0
    }
1735
1736
0
    if (result == FLB_PROCESSOR_SUCCESS) {
1737
0
        result = insert_labels(out_cmt,
1738
0
                               &processor_context->insert_labels);
1739
0
    }
1740
1741
0
    if (result == FLB_PROCESSOR_SUCCESS) {
1742
0
        result = hash_labels(out_cmt,
1743
0
                             &processor_context->hash_labels);
1744
0
    }
1745
1746
0
    if (result != FLB_PROCESSOR_SUCCESS) {
1747
0
        return FLB_PROCESSOR_FAILURE;
1748
0
    }
1749
1750
0
    *out_context = out_cmt;
1751
0
    return FLB_PROCESSOR_SUCCESS;
1752
0
}
1753
1754
static struct flb_config_map config_map[] = {
1755
    {
1756
        FLB_CONFIG_MAP_SLIST_1, "update", NULL,
1757
        FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct internal_processor_context,
1758
                                                update_list),
1759
        "Updates a label. Usage : 'update label_name value'"
1760
    },
1761
    {
1762
        FLB_CONFIG_MAP_SLIST_1, "insert", NULL,
1763
        FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct internal_processor_context,
1764
                                                insert_list),
1765
        "Inserts a label. Usage : 'insert label_name value'"
1766
    },
1767
    {
1768
        FLB_CONFIG_MAP_SLIST_1, "upsert", NULL,
1769
        FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct internal_processor_context,
1770
                                                upsert_list),
1771
        "Inserts or updates a label. Usage : 'upsert label_name value'"
1772
    },
1773
    {
1774
        FLB_CONFIG_MAP_STR, "delete", NULL,
1775
        FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct internal_processor_context,
1776
                                                delete_list),
1777
        "Deletes a label. Usage : 'delete label_name'"
1778
    },
1779
    {
1780
        FLB_CONFIG_MAP_STR, "hash", NULL,
1781
        FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct internal_processor_context,
1782
                                                hash_list),
1783
        "Replaces a labels value with its SHA1 hash. Usage : 'hash label_name'"
1784
    },
1785
1786
    /* EOF */
1787
    {0}
1788
};
1789
1790
struct flb_processor_plugin processor_labels_plugin = {
1791
    .name               = "labels",
1792
    .description        = "Modifies metrics labels",
1793
    .cb_init            = cb_init,
1794
    .cb_process_logs    = NULL,
1795
    .cb_process_metrics = cb_process_metrics,
1796
    .cb_process_traces  = NULL,
1797
    .cb_exit            = cb_exit,
1798
    .config_map         = config_map,
1799
    .flags              = 0
1800
};