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