Coverage Report

Created: 2025-06-24 08:09

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