Coverage Report

Created: 2024-09-19 07:08

/src/fluent-bit/lib/cmetrics/src/cmt_decode_opentelemetry.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
/*  CMetrics
4
 *  ========
5
 *  Copyright 2021-2022 The CMetrics 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 <cmetrics/cmetrics.h>
21
#include <cmetrics/cmt_metric.h>
22
#include <cmetrics/cmt_map.h>
23
#include <cmetrics/cmt_gauge.h>
24
#include <cmetrics/cmt_counter.h>
25
#include <cmetrics/cmt_summary.h>
26
#include <cmetrics/cmt_histogram.h>
27
#include <cmetrics/cmt_untyped.h>
28
#include <cmetrics/cmt_compat.h>
29
#include <cmetrics/cmt_decode_opentelemetry.h>
30
31
static struct cfl_variant *clone_variant(Opentelemetry__Proto__Common__V1__AnyValue *source);
32
33
static int clone_array(struct cfl_array *target,
34
                       Opentelemetry__Proto__Common__V1__ArrayValue *source);
35
static int clone_array_entry(struct cfl_array *target,
36
                             Opentelemetry__Proto__Common__V1__AnyValue *source);
37
static int clone_kvlist(struct cfl_kvlist *target,
38
                                Opentelemetry__Proto__Common__V1__KeyValueList *source);
39
static int clone_kvlist_entry(struct cfl_kvlist *target,
40
                           Opentelemetry__Proto__Common__V1__KeyValue *source);
41
42
static struct cmt_map_label *create_label(char *caption, size_t length);
43
static int append_new_map_label_key(struct cmt_map *map, char *name);
44
static int append_new_metric_label_value(struct cmt_metric *metric, char *name, size_t length);
45
46
static struct cfl_variant *clone_variant(Opentelemetry__Proto__Common__V1__AnyValue *source)
47
0
{
48
0
    struct cfl_kvlist  *new_child_kvlist;
49
0
    struct cfl_array   *new_child_array;
50
0
    struct cfl_variant *result_instance = NULL;
51
0
    int                 result;
52
53
0
    if (source == NULL) {
54
0
        return NULL;
55
0
    }
56
0
    if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE) {
57
0
        result_instance = cfl_variant_create_from_string(source->string_value);
58
0
    }
59
0
    else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BOOL_VALUE) {
60
0
        result_instance = cfl_variant_create_from_bool(source->bool_value);
61
0
    }
62
0
    else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_INT_VALUE) {
63
0
        result_instance = cfl_variant_create_from_int64(source->int_value);
64
0
    }
65
0
    else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_DOUBLE_VALUE) {
66
0
        result_instance = cfl_variant_create_from_double(source->double_value);
67
0
    }
68
0
    else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_KVLIST_VALUE) {
69
0
        new_child_kvlist = cfl_kvlist_create();
70
0
        if (new_child_kvlist == NULL) {
71
0
            return NULL;
72
0
        }
73
74
0
        result_instance = cfl_variant_create_from_kvlist(new_child_kvlist);
75
76
0
        if (result_instance == NULL) {
77
0
            cfl_kvlist_destroy(new_child_kvlist);
78
79
0
            return NULL;
80
0
        }
81
82
0
        result = clone_kvlist(new_child_kvlist, source->kvlist_value);
83
0
        if (result) {
84
0
            cfl_variant_destroy(result_instance);
85
86
0
            return NULL;
87
0
        }
88
0
    }
89
0
    else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_ARRAY_VALUE) {
90
0
        new_child_array = cfl_array_create(source->array_value->n_values);
91
92
0
        if (new_child_array == NULL) {
93
0
            return NULL;
94
0
        }
95
96
0
        result_instance = cfl_variant_create_from_array(new_child_array);
97
0
        if (result_instance == NULL) {
98
0
            cfl_array_destroy(new_child_array);
99
100
0
            return NULL;
101
0
        }
102
103
0
        result = clone_array(new_child_array, source->array_value);
104
0
        if (result) {
105
0
            cfl_variant_destroy(result_instance);
106
107
0
            return NULL;
108
0
        }
109
0
    }
110
0
    else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BYTES_VALUE) {
111
0
        result_instance = cfl_variant_create_from_bytes((char *) source->bytes_value.data, source->bytes_value.len,
112
0
                                                        CFL_FALSE);
113
0
    }
114
115
0
    return result_instance;
116
0
}
117
118
static int clone_array(struct cfl_array *target,
119
                       Opentelemetry__Proto__Common__V1__ArrayValue *source)
120
0
{
121
0
    int    result;
122
0
    size_t index;
123
124
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
125
126
0
    for (index = 0 ;
127
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
128
0
         index < source->n_values ;
129
0
         index++) {
130
0
        result = clone_array_entry(target, source->values[index]);
131
0
    }
132
133
0
    return result;
134
0
}
135
136
static int clone_array_entry(struct cfl_array *target,
137
                             Opentelemetry__Proto__Common__V1__AnyValue *source)
138
0
{
139
0
    struct cfl_variant *new_child_instance;
140
0
    int                 result;
141
142
0
    new_child_instance = clone_variant(source);
143
0
    if (new_child_instance == NULL) {
144
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
145
0
    }
146
147
0
    result = cfl_array_append(target, new_child_instance);
148
0
    if (result) {
149
0
        cfl_variant_destroy(new_child_instance);
150
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
151
0
    }
152
153
0
    return CMT_DECODE_OPENTELEMETRY_SUCCESS;
154
0
}
155
156
static int clone_kvlist(struct cfl_kvlist *target,
157
                        Opentelemetry__Proto__Common__V1__KeyValueList *source)
158
0
{
159
0
    int    result;
160
0
    size_t index;
161
162
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
163
164
0
    for (index = 0 ;
165
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
166
0
         index < source->n_values ;
167
0
         index++) {
168
0
        result = clone_kvlist_entry(target, source->values[index]);
169
0
    }
170
171
0
    return 0;
172
0
}
173
174
static int clone_kvlist_entry(struct cfl_kvlist *target,
175
                              Opentelemetry__Proto__Common__V1__KeyValue *source)
176
0
{
177
0
    struct cfl_variant *new_child_instance;
178
0
    int                 result;
179
180
0
    new_child_instance = clone_variant(source->value);
181
182
0
    if (new_child_instance == NULL) {
183
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
184
0
    }
185
186
0
    result = cfl_kvlist_insert(target, source->key, new_child_instance);
187
188
0
    if (result) {
189
0
        cfl_variant_destroy(new_child_instance);
190
191
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
192
0
    }
193
194
0
    return CMT_DECODE_OPENTELEMETRY_SUCCESS;
195
0
}
196
197
struct cfl_kvlist *get_or_create_external_metadata_kvlist(
198
    struct cfl_kvlist *root, char *key)
199
0
{
200
0
    struct cfl_variant *entry_variant;
201
0
    struct cfl_kvlist  *entry_kvlist;
202
0
    int                 result;
203
204
0
    entry_variant = cfl_kvlist_fetch(root, key);
205
206
0
    if (entry_variant == NULL) {
207
0
        entry_kvlist = cfl_kvlist_create();
208
209
0
        if (entry_kvlist == NULL) {
210
0
            return NULL;
211
0
        }
212
213
0
        result = cfl_kvlist_insert_kvlist(root,
214
0
                                          key,
215
0
                                          entry_kvlist);
216
217
0
        if (result != 0) {
218
0
            cfl_kvlist_destroy(entry_kvlist);
219
220
0
            return NULL;
221
0
        }
222
0
    }
223
0
    else {
224
0
        entry_kvlist = entry_variant->data.as_kvlist;
225
0
    }
226
227
0
    return entry_kvlist;
228
0
}
229
230
static struct cmt_map_label *create_label(char *caption, size_t length)
231
0
{
232
0
    struct cmt_map_label *instance;
233
234
0
    instance = calloc(1, sizeof(struct cmt_map_label));
235
236
0
    if (instance != NULL) {
237
0
        if (caption != NULL) {
238
0
            if (length == 0) {
239
0
                length = strlen(caption);
240
0
            }
241
242
0
            instance->name = cfl_sds_create_len(caption, length);
243
244
0
            if (instance->name == NULL) {
245
0
                cmt_errno();
246
247
0
                free(instance);
248
249
0
                instance = NULL;
250
0
            }
251
0
        }
252
0
    }
253
254
0
    return instance;
255
0
}
256
257
static int append_new_map_label_key(struct cmt_map *map, char *name)
258
0
{
259
0
    struct cmt_map_label *label;
260
261
0
    label = create_label(name, 0);
262
263
0
    if (label == NULL) {
264
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
265
0
    }
266
267
0
    cfl_list_add(&label->_head, &map->label_keys);
268
0
    map->label_count++;
269
270
0
    return CMT_DECODE_OPENTELEMETRY_SUCCESS;
271
0
}
272
273
static int append_new_metric_label_value(struct cmt_metric *metric, char *name, size_t length)
274
0
{
275
0
    struct cmt_map_label *label;
276
277
0
    label = create_label(name, length);
278
279
0
    if (label == NULL) {
280
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
281
0
    }
282
283
0
    cfl_list_add(&label->_head, &metric->labels);
284
285
0
    return CMT_DECODE_OPENTELEMETRY_SUCCESS;
286
0
}
287
288
static int decode_data_point_labels(struct cmt *cmt,
289
                                    struct cmt_map *map,
290
                                    struct cmt_metric *metric,
291
                                    size_t attribute_count,
292
                                    Opentelemetry__Proto__Common__V1__KeyValue **attribute_list)
293
0
{
294
0
    char                                        dummy_label_value[32];
295
0
    void                                      **value_index_list;
296
0
    size_t                                      attribute_index;
297
0
    size_t                                      map_label_index;
298
0
    size_t                                      map_label_count;
299
0
    struct cfl_list                             *label_iterator;
300
0
    struct cmt_map_label                       *current_label;
301
0
    size_t                                      label_index;
302
0
    int                                         label_found;
303
0
    Opentelemetry__Proto__Common__V1__KeyValue *attribute;
304
0
    int                                         result;
305
306
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
307
308
0
    if (attribute_count == 0) {
309
0
        return result;
310
0
    }
311
312
0
    if (attribute_count > 127) {
313
0
        return CMT_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
314
0
    }
315
316
0
    value_index_list = calloc(128, sizeof(void *));
317
318
0
    if (value_index_list == NULL) {
319
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
320
0
    }
321
322
0
    for (attribute_index = 0 ;
323
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
324
0
         attribute_index < attribute_count ;
325
0
         attribute_index++) {
326
327
0
        attribute = attribute_list[attribute_index];
328
329
0
        label_found = CMT_FALSE;
330
0
        label_index = 0;
331
332
0
        cfl_list_foreach(label_iterator, &map->label_keys) {
333
0
            current_label = cfl_list_entry(label_iterator, struct cmt_map_label, _head);
334
335
0
            if (strcmp(current_label->name, attribute->key) == 0) {
336
0
                label_found = CMT_TRUE;
337
338
0
                break;
339
0
            }
340
341
0
            label_index++;
342
0
        }
343
344
0
        if (label_found == CMT_FALSE) {
345
0
            result = append_new_map_label_key(map, attribute->key);
346
0
        }
347
348
0
        if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
349
0
            value_index_list[label_index] = (void *) attribute;
350
0
        }
351
0
    }
352
353
0
    map_label_count = cfl_list_size(&map->label_keys);
354
355
0
    for (map_label_index = 0 ;
356
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
357
0
         map_label_index < map_label_count ;
358
0
         map_label_index++) {
359
360
0
        if (value_index_list[map_label_index] != NULL) {
361
0
            attribute = (Opentelemetry__Proto__Common__V1__KeyValue *)
362
0
                            value_index_list[map_label_index];
363
364
0
            if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE) {
365
0
                result = append_new_metric_label_value(metric, attribute->value->string_value, 0);
366
0
            }
367
0
            else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BYTES_VALUE) {
368
0
                result = append_new_metric_label_value(metric,
369
0
                                                       (char *) attribute->value->bytes_value.data,
370
0
                                                       attribute->value->bytes_value.len);
371
0
            }
372
0
            else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BOOL_VALUE) {
373
0
                snprintf(dummy_label_value, sizeof(dummy_label_value) - 1, "%d", attribute->value->bool_value);
374
375
0
                result = append_new_metric_label_value(metric, dummy_label_value, 0);
376
0
            }
377
0
            else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_INT_VALUE) {
378
0
                snprintf(dummy_label_value, sizeof(dummy_label_value) - 1, "%" PRIi64, attribute->value->int_value);
379
380
0
                result = append_new_metric_label_value(metric, dummy_label_value, 0);
381
0
            }
382
0
            else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_DOUBLE_VALUE) {
383
0
                snprintf(dummy_label_value, sizeof(dummy_label_value) - 1, "%.17g", attribute->value->double_value);
384
385
0
                result = append_new_metric_label_value(metric, dummy_label_value, 0);
386
0
            }
387
0
            else {
388
0
                result = append_new_metric_label_value(metric, NULL, 0);
389
0
            }
390
0
        }
391
0
    }
392
393
0
    free(value_index_list);
394
395
0
    return result;
396
0
}
397
398
static int decode_numerical_data_point(struct cmt *cmt,
399
                                       struct cmt_map *map,
400
                                       Opentelemetry__Proto__Metrics__V1__NumberDataPoint *data_point)
401
0
{
402
0
    int                static_metric_detected;
403
0
    struct cmt_metric *sample;
404
0
    int                result;
405
0
    double             value;
406
407
0
    static_metric_detected = CMT_FALSE;
408
409
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
410
411
0
    if (data_point->n_attributes == 0) {
412
0
        if (map->metric_static_set == CMT_FALSE) {
413
0
            static_metric_detected = CMT_TRUE;
414
0
        }
415
0
    }
416
417
0
    if (static_metric_detected == CMT_FALSE) {
418
0
        sample = calloc(1, sizeof(struct cmt_metric));
419
420
0
        if (sample == NULL) {
421
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
422
0
        }
423
424
0
        cfl_list_init(&sample->labels);
425
426
0
        result = decode_data_point_labels(cmt,
427
0
                                          map,
428
0
                                          sample,
429
0
                                          data_point->n_attributes,
430
0
                                          data_point->attributes);
431
432
0
        if (result) {
433
0
            destroy_label_list(&sample->labels);
434
435
0
            free(sample);
436
0
        }
437
0
        else {
438
0
            cfl_list_add(&sample->_head, &map->metrics);
439
0
        }
440
0
    }
441
0
    else {
442
0
        sample = &map->metric;
443
444
0
        map->metric_static_set = CMT_TRUE;
445
0
    }
446
447
0
    if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
448
0
        value = 0;
449
450
0
        if (data_point->value_case == OPENTELEMETRY__PROTO__METRICS__V1__NUMBER_DATA_POINT__VALUE_AS_INT) {
451
0
            if (data_point->as_int < 0) {
452
0
                value = 0;
453
0
            }
454
0
            else {
455
0
                value = data_point->as_int;
456
0
            }
457
0
        }
458
0
        else if (data_point->value_case == OPENTELEMETRY__PROTO__METRICS__V1__NUMBER_DATA_POINT__VALUE_AS_DOUBLE) {
459
0
            value = data_point->as_double;
460
0
        }
461
462
0
        cmt_metric_set(sample, data_point->time_unix_nano, value);
463
0
    }
464
465
0
    return result;
466
0
}
467
468
static int decode_numerical_data_point_list(struct cmt *cmt,
469
                                            struct cmt_map *map,
470
                                            size_t data_point_count,
471
                                            Opentelemetry__Proto__Metrics__V1__NumberDataPoint **data_point_list)
472
0
{
473
0
    size_t index;
474
0
    int    result;
475
476
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
477
478
0
    for (index = 0 ;
479
0
         result == 0 &&
480
0
         index < data_point_count ; index++) {
481
0
        result = decode_numerical_data_point(cmt, map, data_point_list[index]);
482
0
    }
483
484
0
    return result;
485
0
}
486
487
static int decode_summary_data_point(struct cmt *cmt,
488
                                     struct cmt_map *map,
489
                                     Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *data_point)
490
0
{
491
0
    int                 static_metric_detected;
492
0
    struct cmt_summary *summary;
493
0
    struct cmt_metric  *sample;
494
0
    int                 result;
495
0
    size_t              index;
496
497
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
498
499
0
    summary = (struct cmt_summary *) map->parent;
500
501
0
    if (summary->quantiles == NULL) {
502
0
        summary->quantiles = calloc(data_point->n_quantile_values,
503
0
                                    sizeof(double));
504
505
0
        if (summary->quantiles == NULL) {
506
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
507
0
        }
508
509
0
        summary->quantiles_count = data_point->n_quantile_values;
510
511
0
        for (index = 0 ;
512
0
             index < data_point->n_quantile_values ;
513
0
             index++) {
514
0
            summary->quantiles[index] = data_point->quantile_values[index]->quantile;
515
0
        }
516
0
    }
517
518
0
    static_metric_detected = CMT_FALSE;
519
520
0
    if (data_point->n_attributes == 0) {
521
0
        if (map->metric_static_set == CMT_FALSE) {
522
0
            static_metric_detected = CMT_TRUE;
523
0
        }
524
0
    }
525
526
0
    if (static_metric_detected == CMT_FALSE) {
527
0
        sample = calloc(1, sizeof(struct cmt_metric));
528
529
0
        if (sample == NULL) {
530
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
531
0
        }
532
533
0
        cfl_list_init(&sample->labels);
534
535
0
        result = decode_data_point_labels(cmt,
536
0
                                          map,
537
0
                                          sample,
538
0
                                          data_point->n_attributes,
539
0
                                          data_point->attributes);
540
541
0
        if (result) {
542
0
            destroy_label_list(&sample->labels);
543
544
0
            free(sample);
545
546
0
            return result;
547
0
        }
548
0
        else {
549
0
            cfl_list_add(&sample->_head, &map->metrics);
550
0
        }
551
0
    }
552
0
    else {
553
0
        sample = &map->metric;
554
555
0
        map->metric_static_set = CMT_TRUE;
556
0
    }
557
558
0
    if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
559
0
        if (sample->sum_quantiles_set == CMT_FALSE) {
560
0
            sample->sum_quantiles = calloc(data_point->n_quantile_values,
561
0
                                           sizeof(uint64_t));
562
563
0
            if (sample->sum_quantiles == NULL) {
564
0
                return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
565
0
            }
566
567
0
            sample->sum_quantiles_set = CMT_TRUE;
568
0
            sample->sum_quantiles_count = data_point->n_quantile_values;
569
0
        }
570
571
0
        for (index = 0 ;
572
0
             index < data_point->n_quantile_values ;
573
0
             index++) {
574
0
            cmt_summary_quantile_set(sample, data_point->time_unix_nano,
575
0
                                     index, data_point->quantile_values[index]->value);
576
0
        }
577
578
0
        sample->sum_sum = cmt_math_d64_to_uint64(data_point->sum);
579
0
        sample->sum_count = data_point->count;
580
0
    }
581
582
0
    return result;
583
0
}
584
585
static int decode_summary_data_point_list(struct cmt *cmt,
586
                                          struct cmt_map *map,
587
                                          size_t data_point_count,
588
                                          Opentelemetry__Proto__Metrics__V1__SummaryDataPoint **data_point_list)
589
0
{
590
0
    size_t index;
591
0
    int    result;
592
593
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
594
595
0
    for (index = 0 ;
596
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
597
0
         index < data_point_count ; index++) {
598
0
        result = decode_summary_data_point(cmt, map, data_point_list[index]);
599
0
    }
600
601
0
    return result;
602
0
}
603
604
static int decode_histogram_data_point(struct cmt *cmt,
605
                                       struct cmt_map *map,
606
                                       Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *data_point)
607
0
{
608
0
    int                   static_metric_detected;
609
0
    struct cmt_histogram *histogram;
610
0
    struct cmt_metric    *sample;
611
0
    int                   result;
612
0
    size_t                index;
613
614
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
615
616
0
    histogram = (struct cmt_histogram *) map->parent;
617
618
0
    if (data_point->n_bucket_counts > data_point->n_explicit_bounds + 1) {
619
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
620
0
    }
621
622
0
    if (histogram->buckets == NULL) {
623
0
        histogram->buckets = cmt_histogram_buckets_create_size(data_point->explicit_bounds,
624
0
                                                               data_point->n_explicit_bounds);
625
626
0
        if (histogram->buckets == NULL) {
627
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
628
0
        }
629
0
    }
630
631
0
    static_metric_detected = CMT_FALSE;
632
633
0
    if (data_point->n_attributes == 0) {
634
0
        if (map->metric_static_set == CMT_FALSE) {
635
0
            static_metric_detected = CMT_TRUE;
636
0
        }
637
0
    }
638
639
0
    if (static_metric_detected == CMT_FALSE) {
640
0
        sample = calloc(1, sizeof(struct cmt_metric));
641
642
0
        if (sample == NULL) {
643
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
644
0
        }
645
646
0
        cfl_list_init(&sample->labels);
647
648
0
        result = decode_data_point_labels(cmt,
649
0
                                          map,
650
0
                                          sample,
651
0
                                          data_point->n_attributes,
652
0
                                          data_point->attributes);
653
654
0
        if (result != 0) {
655
0
            destroy_label_list(&sample->labels);
656
657
0
            free(sample);
658
659
0
            return result;
660
0
        }
661
0
        else {
662
0
            cfl_list_add(&sample->_head, &map->metrics);
663
0
        }
664
0
    }
665
0
    else {
666
0
        sample = &map->metric;
667
668
0
        map->metric_static_set = CMT_TRUE;
669
0
    }
670
671
0
    if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
672
0
        if (sample->hist_buckets == NULL) {
673
0
            sample->hist_buckets = calloc(data_point->n_bucket_counts + 1,
674
0
                                          sizeof(uint64_t));
675
676
0
            if (sample->hist_buckets == NULL) {
677
0
                return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
678
0
            }
679
0
        }
680
681
0
        for (index = 0 ;
682
0
             index < data_point->n_bucket_counts;
683
0
             index++) {
684
0
            cmt_metric_hist_set(sample, data_point->time_unix_nano,
685
0
                                index, data_point->bucket_counts[index]);
686
0
        }
687
688
0
        sample->hist_sum = cmt_math_d64_to_uint64(data_point->sum);
689
0
        sample->hist_count = data_point->count;
690
0
    }
691
692
0
    return result;
693
0
}
694
695
static int decode_histogram_data_point_list(struct cmt *cmt,
696
                                            struct cmt_map *map,
697
                                            size_t data_point_count,
698
                                            Opentelemetry__Proto__Metrics__V1__HistogramDataPoint **data_point_list)
699
0
{
700
0
    size_t index;
701
0
    int    result;
702
703
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
704
705
0
    for (index = 0 ;
706
0
         result == 0 &&
707
0
         index < data_point_count ; index++) {
708
0
        result = decode_histogram_data_point(cmt, map, data_point_list[index]);
709
0
    }
710
711
0
    return result;
712
0
}
713
714
static int decode_counter_entry(struct cmt *cmt,
715
    void *instance,
716
    Opentelemetry__Proto__Metrics__V1__Sum *metric)
717
0
{
718
0
    struct cmt_counter *counter;
719
0
    int                 result;
720
721
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
722
723
0
    counter = (struct cmt_counter *) instance;
724
725
0
    counter->map->metric_static_set = 0;
726
727
0
    result = decode_numerical_data_point_list(cmt,
728
0
                                              counter->map,
729
0
                                              metric->n_data_points,
730
0
                                              metric->data_points);
731
732
0
    if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
733
0
        if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_DELTA) {
734
0
            counter->aggregation_type = CMT_AGGREGATION_TYPE_DELTA;
735
0
        }
736
0
        else  if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_CUMULATIVE) {
737
0
            counter->aggregation_type = CMT_AGGREGATION_TYPE_CUMULATIVE;
738
0
        }
739
0
        else {
740
0
            counter->aggregation_type = CMT_AGGREGATION_TYPE_UNSPECIFIED;
741
0
        }
742
743
0
        counter->allow_reset = !metric->is_monotonic;
744
0
    }
745
746
0
    return result;
747
0
}
748
749
static int decode_gauge_entry(struct cmt *cmt,
750
    void *instance,
751
    Opentelemetry__Proto__Metrics__V1__Gauge *metric)
752
0
{
753
0
    struct cmt_gauge *gauge;
754
0
    int               result;
755
756
0
    gauge = (struct cmt_gauge *) instance;
757
758
0
    gauge->map->metric_static_set = 0;
759
760
0
    result = decode_numerical_data_point_list(cmt,
761
0
                                              gauge->map,
762
0
                                              metric->n_data_points,
763
0
                                              metric->data_points);
764
765
0
    return result;
766
0
}
767
768
static int decode_summary_entry(struct cmt *cmt,
769
    void *instance,
770
    Opentelemetry__Proto__Metrics__V1__Summary *metric)
771
0
{
772
0
    struct cmt_summary *summary;
773
0
    int                 result;
774
775
0
    summary = (struct cmt_summary *) instance;
776
777
0
    if (summary->quantiles != NULL) {
778
0
        free(summary->quantiles);
779
0
    }
780
781
0
    summary->quantiles = NULL;
782
0
    summary->quantiles_count = 0;
783
0
    summary->map->metric_static_set = 0;
784
785
0
    result = decode_summary_data_point_list(cmt,
786
0
                                            summary->map,
787
0
                                            metric->n_data_points,
788
0
                                            metric->data_points);
789
790
0
    return result;
791
0
}
792
793
static int decode_histogram_entry(struct cmt *cmt,
794
    void *instance,
795
    Opentelemetry__Proto__Metrics__V1__Histogram *metric)
796
0
{
797
0
    struct cmt_histogram *histogram;
798
0
    int                   result;
799
800
0
    histogram = (struct cmt_histogram *) instance;
801
802
0
    histogram->buckets = NULL;
803
0
    histogram->map->metric_static_set = 0;
804
805
0
    result = decode_histogram_data_point_list(cmt,
806
0
                                              histogram->map,
807
0
                                              metric->n_data_points,
808
0
                                              metric->data_points);
809
810
0
    if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
811
0
        if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_DELTA) {
812
0
            histogram->aggregation_type = CMT_AGGREGATION_TYPE_DELTA;
813
0
        }
814
0
        else  if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_CUMULATIVE) {
815
0
            histogram->aggregation_type = CMT_AGGREGATION_TYPE_CUMULATIVE;
816
0
        }
817
0
        else {
818
0
            histogram->aggregation_type = CMT_AGGREGATION_TYPE_UNSPECIFIED;
819
0
        }
820
0
    }
821
822
0
    return result;
823
0
}
824
825
static int decode_metrics_entry(struct cmt *cmt,
826
    Opentelemetry__Proto__Metrics__V1__Metric *metric)
827
0
{
828
0
    char *metric_description;
829
0
    char *metric_namespace;
830
0
    char *metric_subsystem;
831
0
    char *metric_name;
832
0
    void *instance;
833
0
    int   result;
834
835
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
836
837
0
    metric_name = metric->name;
838
0
    metric_namespace = "";
839
0
    metric_subsystem = "";
840
0
    metric_description = metric->description;
841
842
0
    if (metric_description == NULL) {
843
0
        metric_description = "-";
844
0
    }
845
0
    else if (strlen(metric_description) == 0) {
846
0
        metric_description = "-";
847
0
    }
848
849
0
    if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUM) {
850
0
        instance = cmt_counter_create(cmt,
851
0
                                      metric_namespace,
852
0
                                      metric_subsystem,
853
0
                                      metric_name,
854
0
                                      metric_description,
855
0
                                      0, NULL);
856
857
0
        if (instance == NULL) {
858
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
859
0
        }
860
861
0
        result = decode_counter_entry(cmt, instance, metric->sum);
862
863
0
        if (result) {
864
0
            cmt_counter_destroy(instance);
865
0
        }
866
0
    }
867
0
    else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_GAUGE) {
868
0
        instance = cmt_gauge_create(cmt,
869
0
                                    metric_namespace,
870
0
                                    metric_subsystem,
871
0
                                    metric_name,
872
0
                                    metric_description,
873
0
                                    0, NULL);
874
875
0
        if (instance == NULL) {
876
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
877
0
        }
878
879
0
        result = decode_gauge_entry(cmt, instance, metric->gauge);
880
881
0
        if (result) {
882
0
            cmt_gauge_destroy(instance);
883
0
        }
884
0
    }
885
0
    else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUMMARY) {
886
0
        instance = cmt_summary_create(cmt,
887
0
                                      metric_namespace,
888
0
                                      metric_subsystem,
889
0
                                      metric_name,
890
0
                                      metric_description,
891
0
                                      1, (double []) { 0.0 },
892
0
                                      0, NULL);
893
894
0
        if (instance == NULL) {
895
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
896
0
        }
897
898
        /* We are forced to create at least one quantile by the constructor but we
899
         * don't know the details about it at the moment so we just leave it "open"
900
         */
901
902
0
        result = decode_summary_entry(cmt, instance, metric->summary);
903
904
0
        if (result) {
905
0
            cmt_summary_destroy(instance);
906
0
        }
907
0
    }
908
0
    else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_HISTOGRAM) {
909
0
        instance = cmt_histogram_create(cmt,
910
0
                                        metric_namespace,
911
0
                                        metric_subsystem,
912
0
                                        metric_name,
913
0
                                        metric_description,
914
0
                                        (struct cmt_histogram_buckets *) cmt,
915
0
                                        0, NULL);
916
917
0
        if (instance == NULL) {
918
0
            return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
919
0
        }
920
921
0
        result = decode_histogram_entry(cmt, instance, metric->histogram);
922
923
0
        if (result) {
924
0
            cmt_histogram_destroy(instance);
925
0
        }
926
0
    }
927
928
0
    return result;
929
0
}
930
931
static int decode_scope_metadata_and_attributes(struct cfl_kvlist *external_metadata,
932
    Opentelemetry__Proto__Common__V1__InstrumentationScope *scope)
933
0
{
934
0
    struct cfl_kvlist *attributes;
935
0
    struct cfl_kvlist *metadata;
936
0
    int                result;
937
0
    size_t             index;
938
0
    struct cfl_kvlist *root;
939
940
0
    root = get_or_create_external_metadata_kvlist(external_metadata, "scope");
941
942
0
    if (root == NULL) {
943
0
        return -1;
944
0
    }
945
946
0
    metadata = get_or_create_external_metadata_kvlist(root, "metadata");
947
948
0
    if (metadata == NULL) {
949
0
        return -2;
950
0
    }
951
952
0
    attributes = get_or_create_external_metadata_kvlist(root, "attributes");
953
954
0
    if (attributes == NULL) {
955
0
        return -3;
956
0
    }
957
958
0
    if (scope == NULL) {
959
0
        return 0;
960
0
    }
961
962
0
    if (scope->name != NULL) {
963
0
        result = cfl_kvlist_insert_string(metadata, "name", scope->name);
964
965
0
        if (result != 0) {
966
0
            return -4;
967
0
        }
968
0
    }
969
970
0
    if (scope->version != NULL) {
971
0
        result = cfl_kvlist_insert_string(metadata, "version", scope->version);
972
973
0
        if (result != 0) {
974
0
            return -5;
975
0
        }
976
0
    }
977
978
0
    result = cfl_kvlist_insert_int64(metadata, "dropped_attributes_count", scope->dropped_attributes_count);
979
980
0
    if (result != 0) {
981
0
        return -6;
982
0
    }
983
984
0
    for (index = 0 ;
985
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
986
0
         index < scope->n_attributes ;
987
0
         index++) {
988
0
         result = clone_kvlist_entry(attributes,
989
0
                                     scope->attributes[index]);
990
0
    }
991
992
0
    if (result != 0) {
993
0
        return -7;
994
0
    }
995
996
0
    return 0;
997
0
}
998
999
static int decode_scope_metrics_metadata(struct cfl_kvlist *external_metadata,
1000
    Opentelemetry__Proto__Metrics__V1__ScopeMetrics *scope_metrics)
1001
0
{
1002
0
    struct cfl_kvlist *scope_metrics_metadata;
1003
0
    struct cfl_kvlist *scope_metrics_root;
1004
0
    int                result;
1005
1006
0
    scope_metrics_root = get_or_create_external_metadata_kvlist(external_metadata, "scope_metrics");
1007
1008
0
    if (scope_metrics_root == NULL) {
1009
0
        return -1;
1010
0
    }
1011
1012
0
    scope_metrics_metadata = get_or_create_external_metadata_kvlist(scope_metrics_root, "metadata");
1013
1014
0
    if (scope_metrics_metadata == NULL) {
1015
0
        return -2;
1016
0
    }
1017
1018
0
    if (scope_metrics == NULL) {
1019
0
        return 0;
1020
0
    }
1021
1022
0
    if (scope_metrics->schema_url != NULL) {
1023
0
        result = cfl_kvlist_insert_string(scope_metrics_metadata, "schema_url", scope_metrics->schema_url);
1024
1025
0
        if (result != 0) {
1026
0
            return -3;
1027
0
        }
1028
0
    }
1029
1030
0
    return 0;
1031
0
}
1032
1033
static int decode_scope_metrics_entry(struct cfl_list *context_list,
1034
    Opentelemetry__Proto__Metrics__V1__ScopeMetrics *metrics)
1035
0
{
1036
0
    struct cmt *context;
1037
0
    int         result;
1038
0
    size_t      index;
1039
1040
0
    context = cmt_create();
1041
1042
0
    if (context == NULL) {
1043
0
        return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
1044
0
    }
1045
1046
0
    cfl_list_add(&context->_head, context_list);
1047
1048
0
    result = cfl_kvlist_insert_string(context->internal_metadata,
1049
0
                                      "producer",
1050
0
                                      "opentelemetry");
1051
1052
0
    if (result != 0) {
1053
0
        result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
1054
0
    }
1055
1056
0
    if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
1057
0
        result = decode_scope_metadata_and_attributes(context->external_metadata,
1058
0
                                                      metrics->scope);
1059
1060
0
        if (result != 0) {
1061
0
            result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
1062
0
        }
1063
0
    }
1064
1065
0
    if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
1066
0
        result = decode_scope_metrics_metadata(context->external_metadata,
1067
0
                                               metrics);
1068
1069
0
        if (result != 0) {
1070
0
            result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
1071
0
        }
1072
0
    }
1073
1074
0
    if (result != CMT_DECODE_OPENTELEMETRY_SUCCESS) {
1075
0
        return result;
1076
0
    }
1077
1078
0
    for (index = 0 ;
1079
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
1080
0
         index < metrics->n_metrics ;
1081
0
         index++) {
1082
0
        result = decode_metrics_entry(context,
1083
0
                                      metrics->metrics[index]);
1084
0
    }
1085
1086
0
    return result;
1087
0
}
1088
1089
1090
static int decode_resource_metadata_and_attributes(struct cfl_kvlist *external_metadata,
1091
    Opentelemetry__Proto__Resource__V1__Resource *resource)
1092
0
{
1093
0
    struct cfl_kvlist *attributes;
1094
0
    struct cfl_kvlist *metadata;
1095
0
    int                result;
1096
0
    size_t             index;
1097
0
    struct cfl_kvlist *root;
1098
1099
0
    root = get_or_create_external_metadata_kvlist(external_metadata, "resource");
1100
1101
0
    if (root == NULL) {
1102
0
        return -1;
1103
0
    }
1104
1105
0
    metadata = get_or_create_external_metadata_kvlist(root, "metadata");
1106
1107
0
    if (metadata == NULL) {
1108
0
        return -2;
1109
0
    }
1110
1111
0
    attributes = get_or_create_external_metadata_kvlist(root, "attributes");
1112
1113
0
    if (attributes == NULL) {
1114
0
        return -3;
1115
0
    }
1116
1117
0
    if (resource == NULL) {
1118
0
        return 0;
1119
0
    }
1120
1121
0
    result = cfl_kvlist_insert_int64(metadata, "dropped_attributes_count", (int64_t) resource->dropped_attributes_count);
1122
1123
0
    if (result != 0) {
1124
0
        return -4;
1125
0
    }
1126
1127
0
    for (index = 0 ;
1128
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
1129
0
         index < resource->n_attributes ;
1130
0
         index++) {
1131
0
         result = clone_kvlist_entry(attributes,
1132
0
                                     resource->attributes[index]);
1133
0
    }
1134
1135
0
    if (result != CMT_DECODE_OPENTELEMETRY_SUCCESS) {
1136
0
        return -5;
1137
0
    }
1138
1139
0
    return 0;
1140
0
}
1141
1142
static int decode_resource_metrics_metadata(struct cfl_kvlist *external_metadata,
1143
    Opentelemetry__Proto__Metrics__V1__ResourceMetrics *resource_metrics)
1144
0
{
1145
0
    struct cfl_kvlist *resource_metrics_metadata;
1146
0
    struct cfl_kvlist *resource_metrics_root;
1147
0
    int                result;
1148
1149
0
    resource_metrics_root = get_or_create_external_metadata_kvlist(external_metadata, "resource_metrics");
1150
1151
0
    if (resource_metrics_root == NULL) {
1152
0
        return -1;
1153
0
    }
1154
1155
0
    resource_metrics_metadata = get_or_create_external_metadata_kvlist(resource_metrics_root, "metadata");
1156
1157
0
    if (resource_metrics_metadata == NULL) {
1158
0
        return -2;
1159
0
    }
1160
1161
0
    if (resource_metrics == NULL) {
1162
0
        return 0;
1163
0
    }
1164
1165
0
    if (resource_metrics->schema_url != NULL) {
1166
0
        result = cfl_kvlist_insert_string(resource_metrics_metadata, "schema_url", resource_metrics->schema_url);
1167
1168
0
        if (result != 0) {
1169
0
            return -3;
1170
0
        }
1171
0
    }
1172
1173
0
    return 0;
1174
0
}
1175
1176
static int decode_resource_metrics_entry(
1177
    struct cfl_list *context_list,
1178
    Opentelemetry__Proto__Metrics__V1__ResourceMetrics *resource_metrics)
1179
0
{
1180
0
    struct cmt *context;
1181
0
    int         result;
1182
0
    size_t      index;
1183
1184
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
1185
1186
0
    for (index = 0 ;
1187
0
         result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
1188
0
         index < resource_metrics->n_scope_metrics ;
1189
0
         index++) {
1190
0
        result = decode_scope_metrics_entry(context_list,
1191
0
                    resource_metrics->scope_metrics[index]);
1192
1193
0
        if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
1194
0
            context = cfl_list_entry_last(context_list, struct cmt, _head);
1195
1196
0
            if (context != NULL) {
1197
0
                if (resource_metrics->resource != NULL) {
1198
0
                    result = decode_resource_metadata_and_attributes(context->external_metadata,
1199
0
                                                                     resource_metrics->resource);
1200
1201
0
                    if (result != 0) {
1202
0
                        result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
1203
0
                    }
1204
0
                }
1205
1206
0
                if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
1207
0
                    result = decode_resource_metrics_metadata(context->external_metadata,
1208
0
                                                              resource_metrics);
1209
1210
0
                    if (result != 0) {
1211
0
                        result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
1212
0
                    }
1213
0
                }
1214
0
            }
1215
0
        }
1216
0
    }
1217
1218
0
    return result;
1219
0
}
1220
1221
static void destroy_context_list(struct cfl_list *context_list)
1222
0
{
1223
0
    struct cfl_list *iterator;
1224
0
    struct cmt      *context;
1225
0
    struct cfl_list *tmp;
1226
1227
0
    cfl_list_foreach_safe(iterator, tmp, context_list) {
1228
0
        context = cfl_list_entry(iterator, struct cmt, _head);
1229
1230
0
        cfl_list_del(&context->_head);
1231
1232
0
        cmt_destroy(context);
1233
0
    }
1234
0
}
1235
1236
static int decode_service_request(struct cfl_list *context_list,
1237
    Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *service_request)
1238
0
{
1239
0
    int    result;
1240
0
    size_t index;
1241
1242
0
    result = CMT_DECODE_OPENTELEMETRY_SUCCESS;
1243
1244
0
    if (service_request->n_resource_metrics > 0) {
1245
0
        for (index = 0 ;
1246
0
             result == CMT_DECODE_OPENTELEMETRY_SUCCESS &&
1247
0
             index < service_request->n_resource_metrics ;
1248
0
             index++) {
1249
1250
0
            result = decode_resource_metrics_entry(context_list,
1251
0
                                                   service_request->resource_metrics[index]);
1252
0
        }
1253
0
    }
1254
1255
0
    return result;
1256
0
}
1257
1258
int cmt_decode_opentelemetry_create(struct cfl_list *result_context_list,
1259
                                    char *in_buf, size_t in_size,
1260
                                    size_t *offset)
1261
0
{
1262
0
    Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *service_request;
1263
0
    int                                                                        result;
1264
1265
0
    result = CMT_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
1266
1267
0
    cfl_list_init(result_context_list);
1268
1269
0
    service_request = opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__unpack(NULL, in_size - *offset,
1270
0
                                                                                                           (unsigned char *) &in_buf[*offset]);
1271
1272
0
    if (service_request != NULL) {
1273
0
        result = decode_service_request(result_context_list, service_request);
1274
1275
0
        opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__free_unpacked(service_request, NULL);
1276
0
    }
1277
1278
0
    if (result != CMT_DECODE_OPENTELEMETRY_SUCCESS) {
1279
0
        destroy_context_list(result_context_list);
1280
0
    }
1281
1282
0
    return result;
1283
0
}
1284
1285
void cmt_decode_opentelemetry_destroy(struct cfl_list *context_list)
1286
0
{
1287
0
    if (context_list != NULL) {
1288
0
        destroy_context_list(context_list);
1289
0
    }
1290
0
}