/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 | } |