diff options
Diffstat (limited to '')
40 files changed, 22350 insertions, 0 deletions
diff --git a/fluent-bit/lib/cmetrics/src/CMakeLists.txt b/fluent-bit/lib/cmetrics/src/CMakeLists.txt new file mode 100644 index 00000000..e7db7596 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/CMakeLists.txt @@ -0,0 +1,80 @@ +if (CMT_BUILD_PROMETHEUS_DECODER) + flex_target(cmt_decode_prometheus_lexer cmt_decode_prometheus.l + "${FLEX_BISON_GENERATED_DIR}/cmt_decode_prometheus_lexer.c" + DEFINES_FILE "${FLEX_BISON_GENERATED_DIR}/cmt_decode_prometheus_lexer.h" + ) + bison_target(cmt_decode_prometheus_parser cmt_decode_prometheus.y + "${FLEX_BISON_GENERATED_DIR}/cmt_decode_prometheus_parser.c") + add_flex_bison_dependency(cmt_decode_prometheus_lexer cmt_decode_prometheus_parser) +endif() + +set(src + cmt_gauge.c + cmt_counter.c + cmt_untyped.c + cmt_summary.c + cmt_histogram.c + cmt_metric.c + cmt_metric_histogram.c + cmt_map.c + cmt_log.c + cmt_opts.c + cmt_time.c + cmt_label.c + cmt_cat.c + cmetrics.c + cmt_encode_opentelemetry.c + cmt_decode_opentelemetry.c + cmt_encode_prometheus.c + cmt_encode_prometheus_remote_write.c + cmt_encode_splunk_hec.c + cmt_encode_text.c + cmt_encode_influx.c + cmt_encode_msgpack.c + cmt_decode_msgpack.c + cmt_mpack_utils.c + external/remote.pb-c.c + external/types.pb-c.c + ) + +if (${CMAKE_C_COMPILER_ID} STREQUAL "Clang") + set(PLATFORM_SPECIFIC_ATOMIC_MODULE cmt_atomic_clang.c) +elseif (${CMAKE_C_COMPILER_ID} MATCHES "AppleClang") + set(PLATFORM_SPECIFIC_ATOMIC_MODULE cmt_atomic_clang.c) +elseif (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + set(PLATFORM_SPECIFIC_ATOMIC_MODULE cmt_atomic_gcc.c) +elseif (${CMAKE_C_COMPILER_ID} STREQUAL "MSVC") + set(PLATFORM_SPECIFIC_ATOMIC_MODULE cmt_atomic_msvc.c) +else() + set(PLATFORM_SPECIFIC_ATOMIC_MODULE cmt_atomic_generic.c) +endif() + +set(src + ${src} + ${PLATFORM_SPECIFIC_ATOMIC_MODULE} + ) + +if (CMT_BUILD_PROMETHEUS_DECODER) + set(src ${src} + ${FLEX_cmt_decode_prometheus_lexer_OUTPUTS} + ${BISON_cmt_decode_prometheus_parser_OUTPUTS} + ) +endif() + +# Static Library +add_library(cmetrics-static STATIC ${src}) +target_link_libraries(cmetrics-static mpack-static cfl-static fluent-otel-proto) + +# Install Library +if(MSVC) + # Rename the output for Windows environment to avoid naming issues + set_target_properties(cmetrics-static PROPERTIES OUTPUT_NAME libcmetrics) +else() + set_target_properties(cmetrics-static PROPERTIES OUTPUT_NAME cmetrics) +endif(MSVC) + +install(TARGETS cmetrics-static + RUNTIME DESTINATION ${CMT_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMT_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMT_INSTALL_LIBDIR} + COMPONENT library) diff --git a/fluent-bit/lib/cmetrics/src/cmetrics.c b/fluent-bit/lib/cmetrics/src/cmetrics.c new file mode 100644 index 00000000..9817809d --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmetrics.c @@ -0,0 +1,147 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_atomic.h> +#include <cmetrics/cmt_compat.h> +#include <cmetrics/cmt_label.h> +#include <cmetrics/cmt_version.h> + +#include <cfl/cfl_kvlist.h> + +void cmt_initialize() +{ + cmt_atomic_initialize(); +} + +struct cmt *cmt_create() +{ + struct cmt *cmt; + + cmt = calloc(1, sizeof(struct cmt)); + if (!cmt) { + cmt_errno(); + return NULL; + } + + cmt->static_labels = cmt_labels_create(); + if (!cmt->static_labels) { + free(cmt); + return NULL; + } + + cmt->internal_metadata = cfl_kvlist_create(); + + if (cmt->internal_metadata == NULL) { + cmt_labels_destroy(cmt->static_labels); + + free(cmt); + return NULL; + } + + cmt->external_metadata = cfl_kvlist_create(); + + if (cmt->external_metadata == NULL) { + cfl_kvlist_destroy(cmt->internal_metadata); + cmt_labels_destroy(cmt->static_labels); + + free(cmt); + return NULL; + } + + cfl_list_init(&cmt->counters); + cfl_list_init(&cmt->gauges); + cfl_list_init(&cmt->histograms); + cfl_list_init(&cmt->summaries); + cfl_list_init(&cmt->untypeds); + + cmt->log_level = CMT_LOG_ERROR; + + cfl_list_entry_init(&cmt->_head); + + return cmt; +} + +void cmt_destroy(struct cmt *cmt) +{ + struct cfl_list *tmp; + struct cfl_list *head; + struct cmt_counter *c; + struct cmt_gauge *g; + struct cmt_summary *s; + struct cmt_histogram *h; + struct cmt_untyped *u; + + cfl_list_foreach_safe(head, tmp, &cmt->counters) { + c = cfl_list_entry(head, struct cmt_counter, _head); + cmt_counter_destroy(c); + } + + cfl_list_foreach_safe(head, tmp, &cmt->gauges) { + g = cfl_list_entry(head, struct cmt_gauge, _head); + cmt_gauge_destroy(g); + } + + cfl_list_foreach_safe(head, tmp, &cmt->summaries) { + s = cfl_list_entry(head, struct cmt_summary, _head); + cmt_summary_destroy(s); + } + + cfl_list_foreach_safe(head, tmp, &cmt->histograms) { + h = cfl_list_entry(head, struct cmt_histogram, _head); + cmt_histogram_destroy(h); + } + + cfl_list_foreach_safe(head, tmp, &cmt->untypeds) { + u = cfl_list_entry(head, struct cmt_untyped, _head); + cmt_untyped_destroy(u); + } + + if (cmt->static_labels) { + cmt_labels_destroy(cmt->static_labels); + } + + if (cmt->internal_metadata != NULL) { + cfl_kvlist_destroy(cmt->internal_metadata); + } + + if (cmt->external_metadata != NULL) { + cfl_kvlist_destroy(cmt->external_metadata); + } + + free(cmt); +} + +int cmt_label_add(struct cmt *cmt, char *key, char *val) +{ + return cmt_labels_add_kv(cmt->static_labels, key, val); +} + +char *cmt_version() +{ + return CMT_VERSION_STR; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_atomic_clang.c b/fluent-bit/lib/cmetrics/src/cmt_atomic_clang.c new file mode 100644 index 00000000..5e8734ad --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_atomic_clang.c @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmt_atomic.h> + +inline int cmt_atomic_initialize() +{ + return 0; +} + +inline int cmt_atomic_compare_exchange(uint64_t *storage, + uint64_t old_value, uint64_t new_value) +{ + return __atomic_compare_exchange(storage, &old_value, &new_value, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +} + +inline void cmt_atomic_store(uint64_t *storage, uint64_t new_value) +{ + __atomic_store_n(storage, new_value, __ATOMIC_SEQ_CST); +} + +inline uint64_t cmt_atomic_load(uint64_t *storage) +{ + return __atomic_load_n(storage, __ATOMIC_SEQ_CST); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_atomic_gcc.c b/fluent-bit/lib/cmetrics/src/cmt_atomic_gcc.c new file mode 100644 index 00000000..5e8734ad --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_atomic_gcc.c @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmt_atomic.h> + +inline int cmt_atomic_initialize() +{ + return 0; +} + +inline int cmt_atomic_compare_exchange(uint64_t *storage, + uint64_t old_value, uint64_t new_value) +{ + return __atomic_compare_exchange(storage, &old_value, &new_value, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +} + +inline void cmt_atomic_store(uint64_t *storage, uint64_t new_value) +{ + __atomic_store_n(storage, new_value, __ATOMIC_SEQ_CST); +} + +inline uint64_t cmt_atomic_load(uint64_t *storage) +{ + return __atomic_load_n(storage, __ATOMIC_SEQ_CST); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_atomic_generic.c b/fluent-bit/lib/cmetrics/src/cmt_atomic_generic.c new file mode 100644 index 00000000..40e59b61 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_atomic_generic.c @@ -0,0 +1,123 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <cmetrics/cmt_atomic.h> + +pthread_mutex_t atomic_operation_lock; +static int atomic_operation_system_initialized = 0; + +/* TODO: Determne if we want to keep this backend as well as how / if we want to handle + * pthread_mutex_unlock errors (investigate and understand what could cause them), + * as well as pthread_mutex_lock (determine if we want to apply some sort of retry + * limit there as well) + * + */ + +inline int cmt_atomic_initialize() +{ + int result; + + if (0 == atomic_operation_system_initialized) { + result = pthread_mutex_init(&atomic_operation_lock, NULL); + + if (0 != result) { + return 1; + } + + atomic_operation_system_initialized = 1; + } + + return 0; +} + +inline int cmt_atomic_compare_exchange(uint64_t *storage, + uint64_t old_value, uint64_t new_value) +{ + int result; + + if (0 == atomic_operation_system_initialized) { + printf("CMT ATOMIC : Atomic operation backend not initalized\n"); + exit(1); + } + + result = pthread_mutex_lock(&atomic_operation_lock); + + if (result != 0) { + return 0; + } + + if (*storage == old_value) { + *storage = new_value; + + result = 1; + } + else { + result = 0; + } + + pthread_mutex_unlock(&atomic_operation_lock); + + return result; +} + +inline void cmt_atomic_store(uint64_t *storage, uint64_t new_value) +{ + int result; + + if (0 == atomic_operation_system_initialized) { + printf("CMT ATOMIC : Atomic operation backend not initalized\n"); + exit(1); + } + + result = pthread_mutex_lock(&atomic_operation_lock); + + if (result != 0) { + /* We should notify the user somehow */ + } + + *storage = new_value; + + pthread_mutex_unlock(&atomic_operation_lock); +} + +inline uint64_t cmt_atomic_load(uint64_t *storage) +{ + int result; + uint64_t retval; + + if (0 == atomic_operation_system_initialized) { + printf("CMT ATOMIC : Atomic operation backend not initalized\n"); + exit(1); + } + + result = pthread_mutex_lock(&atomic_operation_lock); + + if (result != 0) { + /* We should notify the user somehow */ + } + + retval = *storage; + + pthread_mutex_unlock(&atomic_operation_lock); + + return retval; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_atomic_msvc.c b/fluent-bit/lib/cmetrics/src/cmt_atomic_msvc.c new file mode 100644 index 00000000..65bfd2f8 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_atomic_msvc.c @@ -0,0 +1,131 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmt_atomic.h> +#include <windows.h> + +/* This allows cmt_atomic_initialize to be automatically called + * as soon as the program starts if enabled. + */ + +#ifndef _WIN64 +CRITICAL_SECTION atomic_operation_lock; +static int atomic_operation_system_initialized = 0; + +int cmt_atomic_initialize() +{ + if (0 == atomic_operation_system_initialized) { + InitializeCriticalSection(&atomic_operation_lock); + + atomic_operation_system_initialized = 1; + } + + return 0; +} + +int cmt_atomic_compare_exchange(uint64_t *storage, + uint64_t old_value, uint64_t new_value) +{ + uint64_t result; + + if (0 == atomic_operation_system_initialized) { + printf("CMT ATOMIC : Atomic operation backend not initalized\n"); + exit(1); + } + + EnterCriticalSection(&atomic_operation_lock); + + if (*storage == old_value) { + *storage = new_value; + + result = 1; + } + else { + result = 0; + } + + LeaveCriticalSection(&atomic_operation_lock); + + return result; +} + +void cmt_atomic_store(uint64_t *storage, uint64_t new_value) +{ + if (0 == atomic_operation_system_initialized) { + printf("CMT ATOMIC : Atomic operation backend not initalized\n"); + exit(1); + } + + EnterCriticalSection(&atomic_operation_lock); + + *storage = new_value; + + LeaveCriticalSection(&atomic_operation_lock); +} + +uint64_t cmt_atomic_load(uint64_t *storage) +{ + uint64_t result; + + if (0 == atomic_operation_system_initialized) { + printf("CMT ATOMIC : Atomic operation backend not initalized\n"); + exit(1); + } + + EnterCriticalSection(&atomic_operation_lock); + + result = *storage; + + LeaveCriticalSection(&atomic_operation_lock); + + return result; +} + +#else /* _WIN64 */ + +int cmt_atomic_initialize() +{ + return 0; +} + +int cmt_atomic_compare_exchange(uint64_t *storage, + uint64_t old_value, uint64_t new_value) +{ + uint64_t result; + + result = _InterlockedCompareExchange64(storage, new_value, old_value); + + if (result != old_value) { + return 0; + } + + return 1; +} + +void cmt_atomic_store(uint64_t *storage, uint64_t new_value) +{ + _InterlockedExchange64(storage, new_value); +} + +uint64_t cmt_atomic_load(uint64_t *storage) +{ + return _InterlockedOr64(storage, 0); +} + +#endif diff --git a/fluent-bit/lib/cmetrics/src/cmt_cat.c b/fluent-bit/lib/cmetrics/src/cmt_cat.c new file mode 100644 index 00000000..5475a98a --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_cat.c @@ -0,0 +1,454 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_summary.h> + +static int copy_label_keys(struct cmt_map *map, char **out) +{ + int i; + int s; + char **labels = NULL; + struct cfl_list *head; + struct cmt_map_label *label; + + /* labels array */ + s = map->label_count; + if (s == 0) { + *out = NULL; + return 0; + } + + if (s > 0) { + labels = malloc(sizeof(char *) * s); + if (!labels) { + cmt_errno(); + return -1; + } + } + + /* label keys: by using the labels array, just point out the names */ + i = 0; + cfl_list_foreach(head, &map->label_keys) { + label = cfl_list_entry(head, struct cmt_map_label, _head); + labels[i] = label->name; + i++; + } + + *out = (char *) labels; + return i; +} + +static int copy_label_values(struct cmt_metric *metric, char **out) +{ + int i; + int s; + char **labels = NULL; + struct cfl_list *head; + struct cmt_map_label *label; + + /* labels array */ + s = cfl_list_size(&metric->labels); + if (s == 0) { + *out = NULL; + return 0; + } + + if (s > 0) { + labels = malloc(sizeof(char *) * s); + if (!labels) { + cmt_errno(); + return -1; + } + } + + /* label keys: by using the labels array, just point out the names */ + i = 0; + cfl_list_foreach(head, &metric->labels) { + label = cfl_list_entry(head, struct cmt_map_label, _head); + labels[i] = label->name; + i++; + } + + *out = (char *) labels; + return i; +} + +static int copy_map(struct cmt_opts *opts, struct cmt_map *dst, struct cmt_map *src) +{ + int i; + int c; + int ret; + uint64_t ts; + double val; + char **labels = NULL; + struct cfl_list *head; + struct cmt_metric *metric_dst; + struct cmt_metric *metric_src; + + /* Handle static metric (no labels case) */ + if (src->metric_static_set) { + dst->metric_static_set = CMT_TRUE; + + /* destination and source metric */ + metric_dst = &dst->metric; + metric_src = &src->metric; + + ts = cmt_metric_get_timestamp(metric_src); + val = cmt_metric_get_value(metric_src); + + cmt_metric_set(metric_dst, ts, val); + } + + /* Process map dynamic metrics */ + cfl_list_foreach(head, &src->metrics) { + metric_src = cfl_list_entry(head, struct cmt_metric, _head); + + ret = copy_label_values(metric_src, (char **) &labels); + if (ret == -1) { + return -1; + } + + c = cfl_list_size(&metric_src->labels); + metric_dst = cmt_map_metric_get(opts, dst, c, labels, CMT_TRUE); + free(labels); + + if (!metric_dst) { + return -1; + } + + if (src->type == CMT_HISTOGRAM) { + if (!metric_dst->hist_buckets) { + metric_dst->hist_buckets = calloc(1, sizeof(uint64_t) * (metric_src->hist_count + 1)); + if (!metric_dst->hist_buckets) { + return -1; + } + } + for (i = 0; i < metric_src->hist_count; i++) { + metric_dst->hist_buckets[i] = metric_src->hist_buckets[i]; + } + metric_dst->hist_count = metric_src->hist_count; + metric_dst->hist_sum = metric_src->hist_sum; + } + else if (src->type == CMT_SUMMARY) { + metric_dst->sum_quantiles_count = metric_src->sum_quantiles_count; + metric_dst->sum_quantiles_set = metric_src->sum_quantiles_set; + if (!metric_dst->sum_quantiles) { + metric_dst->sum_quantiles = calloc(1, sizeof(uint64_t) * (metric_src->sum_quantiles_count)); + if (!metric_dst->sum_quantiles) { + return -1; + } + } + for (i = 0; i < metric_src->sum_quantiles_count; i++) { + metric_dst->sum_quantiles[i] = metric_src->sum_quantiles[i]; + } + metric_dst->sum_count = metric_src->sum_count; + metric_dst->sum_sum = metric_src->sum_sum; + } + + ts = cmt_metric_get_timestamp(metric_src); + val = cmt_metric_get_value(metric_src); + + cmt_metric_set(metric_dst, ts, val); + } + + return 0; + +} + +static int copy_counter(struct cmt *cmt, struct cmt_counter *counter) +{ + int ret; + char **labels = NULL; + struct cmt_map *map; + struct cmt_opts *opts; + struct cmt_counter *c; + + map = counter->map; + opts = map->opts; + + ret = copy_label_keys(map, (char **) &labels); + if (ret == -1) { + return -1; + } + + /* create counter */ + c = cmt_counter_create(cmt, + opts->ns, opts->subsystem, + opts->name, opts->description, + map->label_count, labels); + + free(labels); + if (!c) { + return -1; + } + + ret = copy_map(&c->opts, c->map, map); + if (ret == -1) { + return -1; + } + + return 0; +} + +static int copy_gauge(struct cmt *cmt, struct cmt_gauge *gauge) +{ + int ret; + char **labels = NULL; + struct cmt_map *map; + struct cmt_opts *opts; + struct cmt_gauge *g; + + map = gauge->map; + opts = map->opts; + + ret = copy_label_keys(map, (char **) &labels); + if (ret == -1) { + return -1; + } + + /* create counter */ + g = cmt_gauge_create(cmt, + opts->ns, opts->subsystem, + opts->name, opts->description, + map->label_count, labels); + free(labels); + if (!g) { + return -1; + } + + ret = copy_map(&g->opts, g->map, map); + if (ret == -1) { + return -1; + } + + return 0; +} + +static int copy_untyped(struct cmt *cmt, struct cmt_untyped *untyped) +{ + int ret; + char **labels = NULL; + struct cmt_map *map; + struct cmt_opts *opts; + struct cmt_untyped *u; + + map = untyped->map; + opts = map->opts; + + ret = copy_label_keys(map, (char **) &labels); + if (ret == -1) { + return -1; + } + + /* create counter */ + u = cmt_untyped_create(cmt, + opts->ns, opts->subsystem, + opts->name, opts->description, + map->label_count, labels); + free(labels); + if (!u) { + return -1; + } + + ret = copy_map(&u->opts, u->map, map); + if (ret == -1) { + return -1; + } + + return 0; +} + +static int copy_histogram(struct cmt *cmt, struct cmt_histogram *histogram) +{ + int i; + double val; + int ret; + char **labels = NULL; + struct cmt_map *map; + struct cmt_opts *opts; + struct cmt_histogram *hist; + uint64_t timestamp; + struct cmt_histogram_buckets *buckets; + int64_t buckets_count; + + map = histogram->map; + opts = map->opts; + timestamp = cmt_metric_get_timestamp(&map->metric); + + ret = copy_label_keys(map, (char **) &labels); + if (ret == -1) { + return -1; + } + + buckets_count = histogram->buckets->count; + buckets = cmt_histogram_buckets_create_size(histogram->buckets->upper_bounds, + buckets_count); + + /* create histogram */ + hist = cmt_histogram_create(cmt, + opts->ns, opts->subsystem, + opts->name, opts->description, + buckets, + map->label_count, labels); + if (!hist) { + return -1; + } + + for (i = 0; i < buckets_count; i++) { + val = histogram->buckets->upper_bounds[i]; + cmt_histogram_observe(hist, timestamp, val, map->label_count, labels); + } + free(labels); + + ret = copy_map(&hist->opts, hist->map, map); + if (ret == -1) { + return -1; + } + + return 0; +} + +static int copy_summary(struct cmt *cmt, struct cmt_summary *summary) +{ + int i; + int ret; + char **labels = NULL; + struct cmt_map *map; + struct cmt_opts *opts; + struct cmt_summary *sum; + double *quantiles; + uint64_t timestamp; + double summary_sum; + + map = summary->map; + opts = map->opts; + timestamp = cmt_metric_get_timestamp(&map->metric); + + ret = copy_label_keys(map, (char **) &labels); + if (ret == -1) { + return -1; + } + + quantiles = calloc(1, sizeof(double) * summary->quantiles_count); + for (i = 0; i < summary->quantiles_count; i++) { + quantiles[i] = summary->quantiles[i]; + } + + /* create summary */ + sum = cmt_summary_create(cmt, + opts->ns, opts->subsystem, + opts->name, opts->description, + summary->quantiles_count, + quantiles, + map->label_count, labels); + if (!sum) { + return -1; + } + + summary_sum = cmt_summary_get_sum_value(&summary->map->metric); + + cmt_summary_set_default(sum, timestamp, quantiles, summary_sum, summary->quantiles_count, map->label_count, labels); + free(labels); + free(quantiles); + + ret = copy_map(&sum->opts, sum->map, map); + if (ret == -1) { + return -1; + } + + return 0; +} + +static int append_context(struct cmt *dst, struct cmt *src) +{ + int ret; + struct cfl_list *head; + struct cmt_counter *counter; + struct cmt_gauge *gauge; + struct cmt_untyped *untyped; + struct cmt_histogram *histogram; + struct cmt_summary *summary; + + /* Counters */ + cfl_list_foreach(head, &src->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + ret = copy_counter(dst, counter); + if (ret == -1) { + return -1; + } + } + + /* Gauges */ + cfl_list_foreach(head, &src->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + ret = copy_gauge(dst, gauge); + if (ret == -1) { + return -1; + } + } + + /* Untyped */ + cfl_list_foreach(head, &src->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + ret = copy_untyped(dst, untyped); + if (ret == -1) { + return -1; + } + } + + /* Histogram */ + cfl_list_foreach(head, &src->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + ret = copy_histogram(dst, histogram); + if (ret == -1) { + return -1; + } + } + + /* Summary */ + cfl_list_foreach(head, &src->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + ret = copy_summary(dst, summary); + if (ret == -1) { + return -1; + } + } + + return 0; +} + +int cmt_cat(struct cmt *dst, struct cmt *src) +{ + if (!dst) { + return -1; + } + + if (!src) { + return -1; + } + + return append_context(dst, src); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_counter.c b/fluent-bit/lib/cmetrics/src/cmt_counter.c new file mode 100644 index 00000000..668e9168 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_counter.c @@ -0,0 +1,180 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_counter.h> + +struct cmt_counter *cmt_counter_create(struct cmt *cmt, + char *ns, char *subsystem, + char *name, char *help, + int label_count, char **label_keys) +{ + int ret; + struct cmt_counter *counter; + + if (!ns) { + cmt_log_error(cmt, "null ns not allowed"); + return NULL; + } + + if (!subsystem) { + cmt_log_error(cmt, "null subsystem not allowed"); + return NULL; + } + + if (!name || strlen(name) == 0) { + cmt_log_error(cmt, "undefined name"); + return NULL; + } + + if (!help || strlen(help) == 0) { + cmt_log_error(cmt, "undefined help"); + return NULL; + } + + counter = calloc(1, sizeof(struct cmt_counter)); + if (!counter) { + cmt_errno(); + return NULL; + } + cfl_list_add(&counter->_head, &cmt->counters); + + ret = cmt_opts_init(&counter->opts, ns, subsystem, name, help); + if (ret == -1) { + cmt_log_error(cmt, "unable to initialize options for counter"); + cmt_counter_destroy(counter); + return NULL; + } + + /* Create the map */ + counter->map = cmt_map_create(CMT_COUNTER, &counter->opts, label_count, label_keys, + (void *) counter); + if (!counter->map) { + cmt_log_error(cmt, "unable to allocate map for counter"); + cmt_counter_destroy(counter); + return NULL; + } + /* set default counter aggregation type to cumulative */ + counter->aggregation_type = CMT_AGGREGATION_TYPE_CUMULATIVE; + + counter->cmt = cmt; + return counter; +} + +void cmt_counter_allow_reset(struct cmt_counter *counter) +{ + counter->allow_reset = 1; +} + +int cmt_counter_destroy(struct cmt_counter *counter) +{ + cfl_list_del(&counter->_head); + cmt_opts_exit(&counter->opts); + + if (counter->map) { + cmt_map_destroy(counter->map); + } + free(counter); + return 0; +} + +int cmt_counter_inc(struct cmt_counter *counter, + uint64_t timestamp, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&counter->opts, + counter->map, labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s", + counter->map, counter->opts.ns, counter->opts.subsystem, + counter->opts.name); + return -1; + } + cmt_metric_inc(metric, timestamp); + return 0; +} + +int cmt_counter_add(struct cmt_counter *counter, uint64_t timestamp, double val, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&counter->opts, + counter->map, labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s", + counter->map, counter->opts.ns, counter->opts.subsystem, + counter->opts.name); + return -1; + } + cmt_metric_add(metric, timestamp, val); + return 0; +} + +/* Set counter value, new value cannot be smaller than current value */ +int cmt_counter_set(struct cmt_counter *counter, uint64_t timestamp, double val, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&counter->opts, counter->map, + labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s", + counter->map, counter->opts.ns, counter->opts.subsystem, + counter->opts.name); + return -1; + } + + if (cmt_metric_get_value(metric) > val && counter->allow_reset == 0) { + cmt_log_error(counter->cmt, "attempting to reset unresetable counter: %s_%s_%s", + counter->opts.ns, counter->opts.subsystem, + counter->opts.name); + return -1; + } + cmt_metric_set(metric, timestamp, val); + return 0; +} + +int cmt_counter_get_val(struct cmt_counter *counter, + int labels_count, char **label_vals, double *out_val) +{ + int ret; + double val = 0; + + ret = cmt_map_metric_get_val(&counter->opts, + counter->map, labels_count, label_vals, + &val); + if (ret == -1) { + cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s", + counter->map, counter->opts.ns, counter->opts.subsystem, + counter->opts.name); + return -1; + } + *out_val = val; + return 0; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_decode_msgpack.c b/fluent-bit/lib/cmetrics/src/cmt_decode_msgpack.c new file mode 100644 index 00000000..2e1cf31b --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_decode_msgpack.c @@ -0,0 +1,1474 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_compat.h> +#include <cmetrics/cmt_encode_msgpack.h> +#include <cmetrics/cmt_decode_msgpack.h> +#include <cmetrics/cmt_variant_utils.h> +#include <cmetrics/cmt_mpack_utils.h> + + +static int create_counter_instance(struct cmt_map *map) +{ + struct cmt_counter *counter; + + if (NULL == map) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + counter = calloc(1, sizeof(struct cmt_counter)); + + if (NULL == counter) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + counter->map = map; + + map->parent = (void *) counter; + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int create_gauge_instance(struct cmt_map *map) +{ + struct cmt_gauge *gauge; + + if (NULL == map) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + gauge = calloc(1, sizeof(struct cmt_gauge)); + + if (NULL == gauge) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + gauge->map = map; + + map->parent = (void *) gauge; + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int create_untyped_instance(struct cmt_map *map) +{ + struct cmt_untyped *untyped; + + if (NULL == map) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + untyped = calloc(1, sizeof(struct cmt_untyped)); + + if (NULL == untyped) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + untyped->map = map; + + map->parent = (void *) untyped; + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int create_summary_instance(struct cmt_map *map) +{ + struct cmt_summary *summary; + + if (NULL == map) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + summary = calloc(1, sizeof(struct cmt_summary)); + + if (NULL == summary) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + summary->map = map; + + map->parent = (void *) summary; + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int create_histogram_instance(struct cmt_map *map) +{ + struct cmt_histogram *histogram; + + if (NULL == map) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + histogram = calloc(1, sizeof(struct cmt_histogram)); + + if (NULL == histogram) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + histogram->map = map; + + map->parent = (void *) histogram; + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int create_metric_instance(struct cmt_map *map) +{ + switch(map->type) { + case CMT_COUNTER: + return create_counter_instance(map); + case CMT_GAUGE: + return create_gauge_instance(map); + case CMT_SUMMARY: + return create_summary_instance(map); + case CMT_HISTOGRAM: + return create_histogram_instance(map); + case CMT_UNTYPED: + return create_untyped_instance(map); + } + + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; +} + +static int unpack_opts_ns(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_opts *opts; + + opts = (struct cmt_opts *) context; + + return cmt_mpack_consume_string_tag(reader, &opts->ns); +} + +static int unpack_opts_ss(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_opts *opts; + + opts = (struct cmt_opts *) context; + + return cmt_mpack_consume_string_tag(reader, &opts->subsystem); +} + +static int unpack_opts_name(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_opts *opts; + + opts = (struct cmt_opts *) context; + + return cmt_mpack_consume_string_tag(reader, &opts->name); +} + +static int unpack_opts_desc(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_opts *opts; + + opts = (struct cmt_opts *) context; + + return cmt_mpack_consume_string_tag(reader, &opts->description); +} + +static int unpack_opts(mpack_reader_t *reader, struct cmt_opts *opts) +{ + int result; + struct cmt_mpack_map_entry_callback_t callbacks[] = { + {"ns", unpack_opts_ns}, + {"ss", unpack_opts_ss}, + {"name", unpack_opts_name}, + {"desc", unpack_opts_desc}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == opts ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + memset(opts, 0, sizeof(struct cmt_opts)); + + result = cmt_mpack_unpack_map(reader, callbacks, (void *) opts); + + if (CMT_DECODE_MSGPACK_SUCCESS == result) { + /* Allocate enough space for the three components, the separators + * and the terminator so we don't have to worry about possible realloc issues + * later on. + */ + + opts->fqname = cfl_sds_create_size(cfl_sds_len(opts->ns) + \ + cfl_sds_len(opts->subsystem) + \ + cfl_sds_len(opts->name) + \ + 4); + + if (NULL == opts->fqname) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + cfl_sds_cat(opts->fqname, opts->ns, cfl_sds_len(opts->ns)); + cfl_sds_cat(opts->fqname, "_", 1); + + if (cfl_sds_len(opts->subsystem) > 0) { + cfl_sds_cat(opts->fqname, opts->subsystem, cfl_sds_len(opts->subsystem)); + cfl_sds_cat(opts->fqname, "_", 1); + } + cfl_sds_cat(opts->fqname, opts->name, cfl_sds_len(opts->name)); + } + + return result; +} + +static int unpack_label(mpack_reader_t *reader, + size_t index, + struct cfl_list *target_label_list) +{ + struct cmt_map_label *new_label; + int result; + + if (NULL == reader || + NULL == target_label_list ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + new_label = calloc(1, sizeof(struct cmt_map_label)); + + if (NULL == new_label) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + result = cmt_mpack_consume_string_tag(reader, &new_label->name); + + if (result != CMT_DECODE_MSGPACK_SUCCESS) { + free(new_label); + + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + cfl_list_add(&new_label->_head, target_label_list); + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int unpack_static_label_component(mpack_reader_t *reader, + size_t index, + void *context) +{ + struct cmt_label *label; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + label = (struct cmt_label *) context; + + if (index == 0) { + return cmt_mpack_consume_string_tag(reader, &label->key); + } + else if (index == 1) { + return cmt_mpack_consume_string_tag(reader, &label->val); + } + + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; +} + +static int unpack_static_label(mpack_reader_t *reader, + size_t index, void *context) +{ + struct cfl_list *target_label_list; + struct cmt_label *new_static_label; + struct cmt *decode_context; + int result; + + if (NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt *) context; + + target_label_list = &decode_context->static_labels->list; + + if (NULL == reader || + NULL == target_label_list) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + new_static_label = calloc(1, sizeof(struct cmt_label)); + + if (NULL == new_static_label) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + result = cmt_mpack_unpack_array(reader, + unpack_static_label_component, + new_static_label); + + if (CMT_DECODE_MSGPACK_SUCCESS != result) { + if (new_static_label->key != NULL) { + cfl_sds_destroy(new_static_label->key); + } + + if (new_static_label->val != NULL) { + cfl_sds_destroy(new_static_label->val); + } + + free(new_static_label); + } + else { + cfl_list_add(&new_static_label->_head, target_label_list); + } + + return result; +} + +static int unpack_metric_label(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return unpack_label(reader, + index, + &decode_context->metric->labels); +} + +static int unpack_metric_ts(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_consume_uint_tag(reader, &decode_context->metric->timestamp); +} + +static int unpack_metric_value(mpack_reader_t *reader, size_t index, void *context) +{ + double value; + int result; + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_consume_double_tag(reader, &value); + + if(CMT_DECODE_MSGPACK_SUCCESS == result) { + decode_context->metric->val = cmt_math_d64_to_uint64(value); + } + + return result; +} + +static int unpack_metric_labels(mpack_reader_t *reader, size_t index, void *context) +{ + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_array(reader, + unpack_metric_label, + context); +} + + +static int unpack_summary_quantiles_set(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + int result; + uint64_t value; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_consume_uint_tag(reader, &value); + + if (result == CMT_DECODE_MSGPACK_SUCCESS) { + decode_context->metric->sum_quantiles_set = value; + } + + return result; +} + +static int unpack_summary_quantile(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + return cmt_mpack_consume_uint_tag(reader, &decode_context->metric->sum_quantiles[index]); +} + +static int unpack_summary_quantiles(mpack_reader_t *reader, size_t index, void *context) +{ + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_array(reader, unpack_summary_quantile, context); +} + +static int unpack_summary_count(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_consume_uint_tag(reader, &decode_context->metric->sum_count); +} + +static int unpack_summary_sum(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_consume_uint_tag(reader, &decode_context->metric->sum_sum); +} + +static int unpack_metric_summary(mpack_reader_t *reader, size_t index, void *context) +{ + int result; + struct cmt_msgpack_decode_context *decode_context; + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"quantiles_set", unpack_summary_quantiles_set}, + {"quantiles", unpack_summary_quantiles}, + {"count", unpack_summary_count}, + {"sum", unpack_summary_sum}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_unpack_map(reader, callbacks, (void *) decode_context); + + return result; +} + + +static int unpack_histogram_sum(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + int result; + double value; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_consume_double_tag(reader, &value); + + if (result == CMT_DECODE_MSGPACK_SUCCESS) { + decode_context->metric->hist_sum = cmt_math_d64_to_uint64(value); + } + + return result; +} + +static int unpack_histogram_count(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_consume_uint_tag(reader, &decode_context->metric->hist_count); +} + +static int unpack_histogram_bucket(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_consume_uint_tag(reader, &decode_context->metric->hist_buckets[index]); +} + +static int unpack_histogram_buckets(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_unpack_array(reader, unpack_histogram_bucket, decode_context); +} + +static int unpack_metric_histogram(mpack_reader_t *reader, size_t index, void *context) +{ + int result; + struct cmt_msgpack_decode_context *decode_context; + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"buckets", unpack_histogram_buckets}, + {"count", unpack_histogram_count}, + {"sum", unpack_histogram_sum}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_unpack_map(reader, callbacks, (void *) decode_context); + + return result; +} + + +static int unpack_metric_hash(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_consume_uint_tag(reader, &decode_context->metric->hash); +} + +static int unpack_metric(mpack_reader_t *reader, + struct cmt_msgpack_decode_context *decode_context, + struct cmt_metric **out_metric) +{ + int result; + struct cmt_metric *metric; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"ts", unpack_metric_ts}, + {"value", unpack_metric_value}, + {"labels", unpack_metric_labels}, + {"summary", unpack_metric_summary}, + {"histogram", unpack_metric_histogram}, + {"hash", unpack_metric_hash}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == decode_context || + NULL == out_metric) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + /* Maybe we could move this cmt_metric constructor code to its own file, add a + * destructor and update map_metric_create and map_metric_destroy to use them right? + */ + + metric = calloc(1, sizeof(struct cmt_metric)); + + if (NULL == metric) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + if (decode_context->map->type == CMT_HISTOGRAM) { + histogram = decode_context->map->parent; + + metric->hist_buckets = calloc(histogram->buckets->count + 1, sizeof(uint64_t)); + + if (metric->hist_buckets == NULL) { + cmt_errno(); + + free(metric); + + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + } + else if (decode_context->map->type == CMT_SUMMARY) { + summary = decode_context->map->parent; + + metric->sum_quantiles = calloc(summary->quantiles_count, sizeof(uint64_t)); + + if (metric->sum_quantiles == NULL) { + cmt_errno(); + + free(metric); + + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + metric->sum_quantiles_count = summary->quantiles_count; + } + + cfl_list_init(&metric->labels); + + decode_context->metric = metric; + + result = cmt_mpack_unpack_map(reader, callbacks, (void *) decode_context); + + if (CMT_DECODE_MSGPACK_SUCCESS != result) { + destroy_label_list(&metric->labels); + + if (NULL != metric->hist_buckets) { + free(metric->hist_buckets); + } + + if (NULL != metric->sum_quantiles) { + free(metric->sum_quantiles); + } + + free(metric); + } + else { + *out_metric = metric; + } + + return result; +} + +static int unpack_metric_array_entry(mpack_reader_t *reader, size_t index, void *context) +{ + int result; + struct cmt_metric *metric; + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + metric = NULL; + result = unpack_metric(reader, decode_context, &metric); + + if (CMT_DECODE_MSGPACK_SUCCESS == result) { + if (0 == cfl_list_size(&metric->labels)) { + /* Should we care about finding more than one "implicitly static metric" in + * the array? + */ + decode_context->map->metric_static_set = 1; + + if (decode_context->map->type == CMT_HISTOGRAM) { + decode_context->map->metric.hist_buckets = metric->hist_buckets; + decode_context->map->metric.hist_count = metric->hist_count; + decode_context->map->metric.hist_sum = metric->hist_sum; + } + else if (decode_context->map->type == CMT_SUMMARY) { + decode_context->map->metric.sum_quantiles_set = metric->sum_quantiles_set; + decode_context->map->metric.sum_quantiles = metric->sum_quantiles; + decode_context->map->metric.sum_count = metric->sum_count; + decode_context->map->metric.sum_sum = metric->sum_sum; + } + + decode_context->map->metric.val = metric->val; + decode_context->map->metric.hash = metric->hash; + decode_context->map->metric.timestamp = metric->timestamp; + + free(metric); + } + else + { + cfl_list_add(&metric->_head, &decode_context->map->metrics); + } + } + + return result; +} + +static int unpack_meta_ver(mpack_reader_t *reader, size_t index, void *context) +{ + uint64_t value; + int result; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + result = cmt_mpack_consume_uint_tag(reader, &value); + + if (CMT_DECODE_MSGPACK_SUCCESS == result) { + if (MSGPACK_ENCODER_VERSION != value) { + result = CMT_DECODE_MSGPACK_VERSION_ERROR; + } + } + + return result; +} + +static int unpack_meta_type(mpack_reader_t *reader, size_t index, void *context) +{ + uint64_t value; + int result; + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_consume_uint_tag(reader, &value); + + if (CMT_DECODE_MSGPACK_SUCCESS == result) { + decode_context->map->type = value; + + result = create_metric_instance(decode_context->map); + } + + return result; +} + +static int unpack_meta_aggregation_type(mpack_reader_t *reader, size_t index, void *context) +{ + uint64_t value; + int result; + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_consume_uint_tag(reader, &value); + + if (CMT_DECODE_MSGPACK_SUCCESS == result) { + decode_context->aggregation_type = value; + } + + return result; +} + +static int unpack_meta_opts(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return unpack_opts(reader, decode_context->map->opts); +} + +static int unpack_meta_label(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return unpack_label(reader, + index, + &decode_context->map->label_keys); +} + +static int unpack_meta_static_labels(mpack_reader_t *reader, size_t index, void *context) +{ + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_array(reader, unpack_static_label, context); +} + +static int unpack_meta_labels(mpack_reader_t *reader, size_t index, void *context) +{ + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_array(reader, unpack_meta_label, context); +} + +static int unpack_meta_bucket(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + if (decode_context->bucket_count == 0) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_consume_double_tag(reader, &decode_context->bucket_list[index]); +} + +static int unpack_meta_buckets(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + decode_context->bucket_count = cmt_mpack_peek_array_length(reader); + + if (0 < decode_context->bucket_count) { + decode_context->bucket_list = calloc(decode_context->bucket_count, + sizeof(double)); + + if (NULL == decode_context->bucket_list) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + } + + return cmt_mpack_unpack_array(reader, unpack_meta_bucket, context); +} + +static int unpack_meta_quantile(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + return cmt_mpack_consume_double_tag(reader, &decode_context->quantile_list[index]); +} + +static int unpack_meta_quantiles(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_msgpack_decode_context *decode_context; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + decode_context->quantile_count = cmt_mpack_peek_array_length(reader); + + if (0 < decode_context->quantile_count) { + decode_context->quantile_list = calloc(decode_context->quantile_count, + sizeof(double)); + + if (NULL == decode_context->quantile_list) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + } + + return cmt_mpack_unpack_array(reader, unpack_meta_quantile, context); +} + +static int unpack_basic_type_meta(mpack_reader_t *reader, size_t index, void *context) +{ + int result; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + struct cmt_counter *counter; + struct cmt_msgpack_decode_context *decode_context; + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"ver", unpack_meta_ver}, + {"type", unpack_meta_type}, + {"opts", unpack_meta_opts}, + {"labels", unpack_meta_labels}, + {"buckets", unpack_meta_buckets}, + {"quantiles", unpack_meta_quantiles}, + {"aggregation_type", unpack_meta_aggregation_type}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + decode_context = (struct cmt_msgpack_decode_context *) context; + + result = cmt_mpack_unpack_map(reader, callbacks, context); + + if (CMT_DECODE_MSGPACK_SUCCESS == result) { + decode_context->map->label_count = cfl_list_size(&decode_context->map->label_keys); + + if (decode_context->map->type == CMT_HISTOGRAM) { + histogram = (struct cmt_histogram *) decode_context->map->parent; + + if (decode_context->bucket_count > 0) { + histogram->buckets = + cmt_histogram_buckets_create_size(decode_context->bucket_list, + decode_context->bucket_count); + + if (histogram->buckets == NULL) { + result = CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + } + else { + histogram->buckets = NULL; + } + } + else if (decode_context->map->type == CMT_SUMMARY) { + summary = (struct cmt_summary *) decode_context->map->parent; + + summary->quantiles = decode_context->quantile_list; + summary->quantiles_count = decode_context->quantile_count; + + decode_context->quantile_list = NULL; + decode_context->quantile_count = 0; + } + else if(decode_context->map->type == CMT_COUNTER) { + counter = (struct cmt_counter *) decode_context->map->parent; + counter->aggregation_type = decode_context->aggregation_type; + } + } + + return result; +} + +static int unpack_basic_type_values(mpack_reader_t *reader, size_t index, void *context) +{ + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_array(reader, + unpack_metric_array_entry, + context); +} + +static int unpack_basic_type(mpack_reader_t *reader, struct cmt *cmt, struct cmt_map **map) +{ + int result; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + struct cmt_msgpack_decode_context decode_context; + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"meta", unpack_basic_type_meta}, + {"values", unpack_basic_type_values}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == map) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + memset(&decode_context, 0, sizeof(struct cmt_msgpack_decode_context)); + + *map = cmt_map_create(0, NULL, 0, NULL, NULL); + + if (NULL == *map) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + (*map)->metric_static_set = 0; + (*map)->opts = calloc(1, sizeof(struct cmt_opts)); + + if (NULL == (*map)->opts) { + cmt_map_destroy(*map); + + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + decode_context.cmt = cmt; + decode_context.map = *map; + + result = cmt_mpack_unpack_map(reader, callbacks, (void *) &decode_context); + + if ((*map)->parent == NULL) { + result = CMT_DECODE_MSGPACK_CORRUPT_INPUT_DATA_ERROR; + } + + if (CMT_DECODE_MSGPACK_SUCCESS != result) { + if ((*map)->opts != NULL) { + cmt_opts_exit((*map)->opts); + + free((*map)->opts); + } + + if ((*map)->parent != NULL) { + if ((*map)->type == CMT_HISTOGRAM) { + histogram = ((struct cmt_histogram *) (*map)->parent); + + if (NULL != histogram->buckets) { + if (NULL != histogram->buckets->upper_bounds) { + free(histogram->buckets->upper_bounds); + } + + free(histogram->buckets); + } + } + else if ((*map)->type == CMT_SUMMARY) { + summary = ((struct cmt_summary *) (*map)->parent); + + if (NULL != summary->quantiles) { + free(summary->quantiles); + } + } + + free((*map)->parent); + } + + cmt_map_destroy(*map); + + *map = NULL; + } + + if (decode_context.bucket_list != NULL) { + free(decode_context.bucket_list); + } + + if (decode_context.quantile_list != NULL) { + free(decode_context.quantile_list); + } + + return result; +} + +static int append_unpacked_counter_to_metrics_context(struct cmt *context, + struct cmt_map *map) +{ + struct cmt_counter *counter; + + if (NULL == context || + NULL == map ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + counter = map->parent; + + if (NULL == counter) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + counter->cmt = context; + counter->map = map; + map->parent = (void *) counter; + + memcpy(&counter->opts, map->opts, sizeof(struct cmt_opts)); + + free(map->opts); + + map->opts = &counter->opts; + + cfl_list_add(&counter->_head, &context->counters); + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int append_unpacked_gauge_to_metrics_context(struct cmt *context, + struct cmt_map *map) +{ + struct cmt_gauge *gauge; + + if (NULL == context || + NULL == map ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + gauge = map->parent; + + if (NULL == gauge) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + gauge->cmt = context; + gauge->map = map; + map->parent = (void *) gauge; + + memcpy(&gauge->opts, map->opts, sizeof(struct cmt_opts)); + + free(map->opts); + + map->opts = &gauge->opts; + + cfl_list_add(&gauge->_head, &context->gauges); + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int append_unpacked_untyped_to_metrics_context(struct cmt *context, + struct cmt_map *map) +{ + struct cmt_untyped *untyped; + + if (NULL == context || + NULL == map ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + untyped = map->parent; + if (NULL == untyped) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + untyped->cmt = context; + untyped->map = map; + map->parent = (void *) untyped; + + memcpy(&untyped->opts, map->opts, sizeof(struct cmt_opts)); + + free(map->opts); + + map->opts = &untyped->opts; + + cfl_list_add(&untyped->_head, &context->untypeds); + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int append_unpacked_summary_to_metrics_context(struct cmt *context, + struct cmt_map *map) +{ + struct cmt_summary *summary; + + if (NULL == context || + NULL == map ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + summary = map->parent; + if (NULL == summary) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + summary->cmt = context; + summary->map = map; + map->parent = (void *) summary; + + memcpy(&summary->opts, map->opts, sizeof(struct cmt_opts)); + + free(map->opts); + + map->opts = &summary->opts; + + cfl_list_add(&summary->_head, &context->summaries); + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int append_unpacked_histogram_to_metrics_context( + struct cmt *context, + struct cmt_map *map) +{ + struct cmt_histogram *histogram; + + if (NULL == context || + NULL == map ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + histogram = map->parent; + if (NULL == histogram) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + histogram->cmt = context; + histogram->map = map; + map->parent = (void *) histogram; + + memcpy(&histogram->opts, map->opts, sizeof(struct cmt_opts)); + + free(map->opts); + + map->opts = &histogram->opts; + + cfl_list_add(&histogram->_head, &context->histograms); + + return CMT_DECODE_MSGPACK_SUCCESS; +} + +static int unpack_basic_type_entry(mpack_reader_t *reader, size_t index, void *context) +{ + int result; + struct cmt *cmt; + struct cmt_map *map; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + cmt = (struct cmt *) context; + + result = unpack_basic_type(reader, cmt, &map); + + if (CMT_DECODE_MSGPACK_SUCCESS == result) { + if (CMT_COUNTER == map->type) { + result = append_unpacked_counter_to_metrics_context(cmt, map); + } + else if (CMT_GAUGE == map->type) { + result = append_unpacked_gauge_to_metrics_context(cmt, map); + } + else if (CMT_SUMMARY == map->type) { + result = append_unpacked_summary_to_metrics_context(cmt, map); + } + else if (CMT_HISTOGRAM == map->type) { + result = append_unpacked_histogram_to_metrics_context(cmt, map); + } + else if (CMT_UNTYPED == map->type) { + result = append_unpacked_untyped_to_metrics_context(cmt, map); + } + } + + return result; +} + +static int unpack_context_internal_metadata(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt *metrics_context; + int result; + + metrics_context = (struct cmt *) context; + + if (metrics_context->internal_metadata != NULL) { + cfl_kvlist_destroy(metrics_context->internal_metadata); + + metrics_context->internal_metadata = NULL; + } + + result = unpack_cfl_kvlist(reader, &metrics_context->internal_metadata); + + if (result == 0) { + result = CMT_DECODE_MSGPACK_SUCCESS; + } + else { + result = CMT_DECODE_MSGPACK_CORRUPT_INPUT_DATA_ERROR; + } + + return result; +} + +static int unpack_context_external_metadata(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt *metrics_context; + int result; + + metrics_context = (struct cmt *) context; + + if (metrics_context->external_metadata != NULL) { + cfl_kvlist_destroy(metrics_context->external_metadata); + + metrics_context->external_metadata = NULL; + } + + result = unpack_cfl_kvlist(reader, &metrics_context->external_metadata); + + if (result == 0) { + result = CMT_DECODE_MSGPACK_SUCCESS; + } + else { + result = CMT_DECODE_MSGPACK_CORRUPT_INPUT_DATA_ERROR; + } + + return result; +} + +static int unpack_context_processing_section(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"static_labels", unpack_meta_static_labels}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_map(reader, callbacks, context); +} + +static int unpack_context_header(mpack_reader_t *reader, size_t index, void *context) +{ + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"cmetrics", unpack_context_internal_metadata}, + {"external", unpack_context_external_metadata}, + {"processing", unpack_context_processing_section}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_map(reader, callbacks, context); +} + +static int unpack_context_metrics(mpack_reader_t *reader, size_t index, void *context) +{ + if (NULL == reader || + NULL == context) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_array(reader, + unpack_basic_type_entry, + context); +} + +static int unpack_context(mpack_reader_t *reader, struct cmt *cmt) +{ + struct cmt_mpack_map_entry_callback_t callbacks[] = \ + { + {"meta", unpack_context_header}, + {"metrics", unpack_context_metrics}, + {NULL, NULL} + }; + + if (NULL == reader || + NULL == cmt) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + return cmt_mpack_unpack_map(reader, callbacks, (void *) cmt); +} + +/* Convert cmetrics msgpack payload and generate a CMetrics context */ +int cmt_decode_msgpack_create(struct cmt **out_cmt, char *in_buf, size_t in_size, + size_t *offset) +{ + struct cmt *cmt; + mpack_reader_t reader; + int result; + size_t remainder; + + if (NULL == out_cmt || + NULL == in_buf || + NULL == offset || + in_size < *offset ) { + return CMT_DECODE_MSGPACK_INVALID_ARGUMENT_ERROR; + } + + if (0 == in_size || + 0 == (in_size - *offset) ) { + return CMT_DECODE_MSGPACK_INSUFFICIENT_DATA; + } + + cmt = cmt_create(); + + if (NULL == cmt) { + return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; + } + + in_size -= *offset; + + mpack_reader_init_data(&reader, &in_buf[*offset], in_size); + + result = unpack_context(&reader, cmt); + + remainder = mpack_reader_remaining(&reader, NULL); + + *offset += in_size - remainder; + + mpack_reader_destroy(&reader); + + if (CMT_DECODE_MSGPACK_SUCCESS != result) { + cmt_destroy(cmt); + } + else { + *out_cmt = cmt; + } + + return result; +} + +void cmt_decode_msgpack_destroy(struct cmt *cmt) +{ + if (NULL != cmt) { + cmt_destroy(cmt); + } +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_decode_opentelemetry.c b/fluent-bit/lib/cmetrics/src/cmt_decode_opentelemetry.c new file mode 100644 index 00000000..aad42507 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_decode_opentelemetry.c @@ -0,0 +1,1289 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_compat.h> +#include <cmetrics/cmt_decode_opentelemetry.h> + +static struct cfl_variant *clone_variant(Opentelemetry__Proto__Common__V1__AnyValue *source); + +static int clone_array(struct cfl_array *target, + Opentelemetry__Proto__Common__V1__ArrayValue *source); +static int clone_array_entry(struct cfl_array *target, + Opentelemetry__Proto__Common__V1__AnyValue *source); +static int clone_kvlist(struct cfl_kvlist *target, + Opentelemetry__Proto__Common__V1__KeyValueList *source); +static int clone_kvlist_entry(struct cfl_kvlist *target, + Opentelemetry__Proto__Common__V1__KeyValue *source); + +static struct cmt_map_label *create_label(char *caption, size_t length); +static int append_new_map_label_key(struct cmt_map *map, char *name); +static int append_new_metric_label_value(struct cmt_metric *metric, char *name, size_t length); + +static struct cfl_variant *clone_variant(Opentelemetry__Proto__Common__V1__AnyValue *source) +{ + struct cfl_kvlist *new_child_kvlist; + struct cfl_array *new_child_array; + struct cfl_variant *result_instance = NULL; + int result; + + if (source == NULL) { + return NULL; + } + if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE) { + result_instance = cfl_variant_create_from_string(source->string_value); + } + else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BOOL_VALUE) { + result_instance = cfl_variant_create_from_bool(source->bool_value); + } + else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_INT_VALUE) { + result_instance = cfl_variant_create_from_int64(source->int_value); + } + else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_DOUBLE_VALUE) { + result_instance = cfl_variant_create_from_double(source->double_value); + } + else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_KVLIST_VALUE) { + new_child_kvlist = cfl_kvlist_create(); + if (new_child_kvlist == NULL) { + return NULL; + } + + result_instance = cfl_variant_create_from_kvlist(new_child_kvlist); + + if (result_instance == NULL) { + cfl_kvlist_destroy(new_child_kvlist); + + return NULL; + } + + result = clone_kvlist(new_child_kvlist, source->kvlist_value); + if (result) { + cfl_variant_destroy(result_instance); + + return NULL; + } + } + else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_ARRAY_VALUE) { + new_child_array = cfl_array_create(source->array_value->n_values); + + if (new_child_array == NULL) { + return NULL; + } + + result_instance = cfl_variant_create_from_array(new_child_array); + if (result_instance == NULL) { + cfl_array_destroy(new_child_array); + + return NULL; + } + + result = clone_array(new_child_array, source->array_value); + if (result) { + cfl_variant_destroy(result_instance); + + return NULL; + } + } + else if (source->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BYTES_VALUE) { + result_instance = cfl_variant_create_from_bytes((char *) source->bytes_value.data, source->bytes_value.len); + } + + return result_instance; +} + +static int clone_array(struct cfl_array *target, + Opentelemetry__Proto__Common__V1__ArrayValue *source) +{ + int result; + size_t index; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < source->n_values ; + index++) { + result = clone_array_entry(target, source->values[index]); + } + + return result; +} + +static int clone_array_entry(struct cfl_array *target, + Opentelemetry__Proto__Common__V1__AnyValue *source) +{ + struct cfl_variant *new_child_instance; + int result; + + new_child_instance = clone_variant(source); + if (new_child_instance == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + result = cfl_array_append(target, new_child_instance); + if (result) { + cfl_variant_destroy(new_child_instance); + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + return CMT_DECODE_OPENTELEMETRY_SUCCESS; +} + +static int clone_kvlist(struct cfl_kvlist *target, + Opentelemetry__Proto__Common__V1__KeyValueList *source) +{ + int result; + size_t index; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < source->n_values ; + index++) { + result = clone_kvlist_entry(target, source->values[index]); + } + + return 0; +} + +static int clone_kvlist_entry(struct cfl_kvlist *target, + Opentelemetry__Proto__Common__V1__KeyValue *source) +{ + struct cfl_variant *new_child_instance; + int result; + + new_child_instance = clone_variant(source->value); + + if (new_child_instance == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + result = cfl_kvlist_insert(target, source->key, new_child_instance); + + if (result) { + cfl_variant_destroy(new_child_instance); + + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + return CMT_DECODE_OPENTELEMETRY_SUCCESS; +} + +struct cfl_kvlist *get_or_create_external_metadata_kvlist( + struct cfl_kvlist *root, char *key) +{ + struct cfl_variant *entry_variant; + struct cfl_kvlist *entry_kvlist; + int result; + + entry_variant = cfl_kvlist_fetch(root, key); + + if (entry_variant == NULL) { + entry_kvlist = cfl_kvlist_create(); + + if (entry_kvlist == NULL) { + return NULL; + } + + result = cfl_kvlist_insert_kvlist(root, + key, + entry_kvlist); + + if (result != 0) { + cfl_kvlist_destroy(entry_kvlist); + + return NULL; + } + } + else { + entry_kvlist = entry_variant->data.as_kvlist; + } + + return entry_kvlist; +} + +static struct cmt_map_label *create_label(char *caption, size_t length) +{ + struct cmt_map_label *instance; + + instance = calloc(1, sizeof(struct cmt_map_label)); + + if (instance != NULL) { + if (caption != NULL) { + if (length == 0) { + length = strlen(caption); + } + + instance->name = cfl_sds_create_len(caption, length); + + if (instance->name == NULL) { + cmt_errno(); + + free(instance); + + instance = NULL; + } + } + } + + return instance; +} + +static int append_new_map_label_key(struct cmt_map *map, char *name) +{ + struct cmt_map_label *label; + + label = create_label(name, 0); + + if (label == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + cfl_list_add(&label->_head, &map->label_keys); + map->label_count++; + + return CMT_DECODE_OPENTELEMETRY_SUCCESS; +} + +static int append_new_metric_label_value(struct cmt_metric *metric, char *name, size_t length) +{ + struct cmt_map_label *label; + + label = create_label(name, length); + + if (label == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + cfl_list_add(&label->_head, &metric->labels); + + return CMT_DECODE_OPENTELEMETRY_SUCCESS; +} + +static int decode_data_point_labels(struct cmt *cmt, + struct cmt_map *map, + struct cmt_metric *metric, + size_t attribute_count, + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list) +{ + char dummy_label_value[32]; + void **value_index_list; + size_t attribute_index; + size_t map_label_index; + size_t map_label_count; + struct cfl_list *label_iterator; + struct cmt_map_label *current_label; + size_t label_index; + int label_found; + Opentelemetry__Proto__Common__V1__KeyValue *attribute; + int result; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + if (attribute_count == 0) { + return result; + } + + if (attribute_count > 127) { + return CMT_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; + } + + value_index_list = calloc(128, sizeof(void *)); + + if (value_index_list == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + for (attribute_index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + attribute_index < attribute_count ; + attribute_index++) { + + attribute = attribute_list[attribute_index]; + + label_found = CMT_FALSE; + label_index = 0; + + cfl_list_foreach(label_iterator, &map->label_keys) { + current_label = cfl_list_entry(label_iterator, struct cmt_map_label, _head); + + if (strcmp(current_label->name, attribute->key) == 0) { + label_found = CMT_TRUE; + + break; + } + + label_index++; + } + + if (label_found == CMT_FALSE) { + result = append_new_map_label_key(map, attribute->key); + } + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + value_index_list[label_index] = (void *) attribute; + } + } + + map_label_count = cfl_list_size(&map->label_keys); + + for (map_label_index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + map_label_index < map_label_count ; + map_label_index++) { + + if (value_index_list[map_label_index] != NULL) { + attribute = (Opentelemetry__Proto__Common__V1__KeyValue *) + value_index_list[map_label_index]; + + if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE) { + result = append_new_metric_label_value(metric, attribute->value->string_value, 0); + } + else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BYTES_VALUE) { + result = append_new_metric_label_value(metric, + (char *) attribute->value->bytes_value.data, + attribute->value->bytes_value.len); + } + else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BOOL_VALUE) { + snprintf(dummy_label_value, sizeof(dummy_label_value) - 1, "%d", attribute->value->bool_value); + + result = append_new_metric_label_value(metric, dummy_label_value, 0); + } + else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_INT_VALUE) { + snprintf(dummy_label_value, sizeof(dummy_label_value) - 1, "%" PRIi64, attribute->value->int_value); + + result = append_new_metric_label_value(metric, dummy_label_value, 0); + } + else if (attribute->value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_DOUBLE_VALUE) { + snprintf(dummy_label_value, sizeof(dummy_label_value) - 1, "%.17g", attribute->value->double_value); + + result = append_new_metric_label_value(metric, dummy_label_value, 0); + } + else { + result = append_new_metric_label_value(metric, NULL, 0); + } + } + } + + free(value_index_list); + + return result; +} + +static int decode_numerical_data_point(struct cmt *cmt, + struct cmt_map *map, + Opentelemetry__Proto__Metrics__V1__NumberDataPoint *data_point) +{ + int static_metric_detected; + struct cmt_metric *sample; + int result; + double value; + + static_metric_detected = CMT_FALSE; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + if (data_point->n_attributes == 0) { + if (map->metric_static_set == CMT_FALSE) { + static_metric_detected = CMT_TRUE; + } + } + + if (static_metric_detected == CMT_FALSE) { + sample = calloc(1, sizeof(struct cmt_metric)); + + if (sample == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + cfl_list_init(&sample->labels); + + result = decode_data_point_labels(cmt, + map, + sample, + data_point->n_attributes, + data_point->attributes); + + if (result) { + destroy_label_list(&sample->labels); + + free(sample); + } + else { + cfl_list_add(&sample->_head, &map->metrics); + } + } + else { + sample = &map->metric; + + map->metric_static_set = CMT_TRUE; + } + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + value = 0; + + if (data_point->value_case == OPENTELEMETRY__PROTO__METRICS__V1__NUMBER_DATA_POINT__VALUE_AS_INT) { + if (data_point->as_int < 0) { + value = 0; + } + else { + value = cmt_math_uint64_to_d64((uint64_t) data_point->as_int); + } + } + else if (data_point->value_case == OPENTELEMETRY__PROTO__METRICS__V1__NUMBER_DATA_POINT__VALUE_AS_DOUBLE) { + value = data_point->as_double; + } + + cmt_metric_set(sample, data_point->time_unix_nano, value); + } + + return result; +} + +static int decode_numerical_data_point_list(struct cmt *cmt, + struct cmt_map *map, + size_t data_point_count, + Opentelemetry__Proto__Metrics__V1__NumberDataPoint **data_point_list) +{ + size_t index; + int result; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + for (index = 0 ; + result == 0 && + index < data_point_count ; index++) { + result = decode_numerical_data_point(cmt, map, data_point_list[index]); + } + + return result; +} + +static int decode_summary_data_point(struct cmt *cmt, + struct cmt_map *map, + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *data_point) +{ + int static_metric_detected; + struct cmt_summary *summary; + struct cmt_metric *sample; + int result; + size_t index; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + summary = (struct cmt_summary *) map->parent; + + if (summary->quantiles == NULL) { + summary->quantiles = calloc(data_point->n_quantile_values, + sizeof(double)); + + if (summary->quantiles == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + summary->quantiles_count = data_point->n_quantile_values; + + for (index = 0 ; + index < data_point->n_quantile_values ; + index++) { + summary->quantiles[index] = data_point->quantile_values[index]->quantile; + } + } + + static_metric_detected = CMT_FALSE; + + if (data_point->n_attributes == 0) { + if (map->metric_static_set == CMT_FALSE) { + static_metric_detected = CMT_TRUE; + } + } + + if (static_metric_detected == CMT_FALSE) { + sample = calloc(1, sizeof(struct cmt_metric)); + + if (sample == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + cfl_list_init(&sample->labels); + + result = decode_data_point_labels(cmt, + map, + sample, + data_point->n_attributes, + data_point->attributes); + + if (result) { + destroy_label_list(&sample->labels); + + free(sample); + + return result; + } + else { + cfl_list_add(&sample->_head, &map->metrics); + } + } + else { + sample = &map->metric; + + map->metric_static_set = CMT_TRUE; + } + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + if (sample->sum_quantiles_set == CMT_FALSE) { + sample->sum_quantiles = calloc(data_point->n_quantile_values, + sizeof(uint64_t)); + + if (sample->sum_quantiles == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + sample->sum_quantiles_set = CMT_TRUE; + sample->sum_quantiles_count = data_point->n_quantile_values; + } + + for (index = 0 ; + index < data_point->n_quantile_values ; + index++) { + cmt_summary_quantile_set(sample, data_point->time_unix_nano, + index, data_point->quantile_values[index]->value); + } + + sample->sum_sum = cmt_math_d64_to_uint64(data_point->sum); + sample->sum_count = data_point->count; + } + + return result; +} + +static int decode_summary_data_point_list(struct cmt *cmt, + struct cmt_map *map, + size_t data_point_count, + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint **data_point_list) +{ + size_t index; + int result; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < data_point_count ; index++) { + result = decode_summary_data_point(cmt, map, data_point_list[index]); + } + + return result; +} + +static int decode_histogram_data_point(struct cmt *cmt, + struct cmt_map *map, + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *data_point) +{ + int static_metric_detected; + struct cmt_histogram *histogram; + struct cmt_metric *sample; + int result; + size_t index; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + histogram = (struct cmt_histogram *) map->parent; + + if (data_point->n_bucket_counts > data_point->n_explicit_bounds + 1) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + if (histogram->buckets == NULL) { + histogram->buckets = cmt_histogram_buckets_create_size(data_point->explicit_bounds, + data_point->n_explicit_bounds); + + if (histogram->buckets == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + } + + static_metric_detected = CMT_FALSE; + + if (data_point->n_attributes == 0) { + if (map->metric_static_set == CMT_FALSE) { + static_metric_detected = CMT_TRUE; + } + } + + if (static_metric_detected == CMT_FALSE) { + sample = calloc(1, sizeof(struct cmt_metric)); + + if (sample == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + cfl_list_init(&sample->labels); + + result = decode_data_point_labels(cmt, + map, + sample, + data_point->n_attributes, + data_point->attributes); + + if (result != 0) { + destroy_label_list(&sample->labels); + + free(sample); + + return result; + } + else { + cfl_list_add(&sample->_head, &map->metrics); + } + } + else { + sample = &map->metric; + + map->metric_static_set = CMT_TRUE; + } + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + if (sample->hist_buckets == NULL) { + sample->hist_buckets = calloc(data_point->n_bucket_counts + 1, + sizeof(uint64_t)); + + if (sample->hist_buckets == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + } + + for (index = 0 ; + index < data_point->n_bucket_counts; + index++) { + cmt_metric_hist_set(sample, data_point->time_unix_nano, + index, data_point->bucket_counts[index]); + } + + sample->hist_sum = cmt_math_d64_to_uint64(data_point->sum); + sample->hist_count = data_point->count; + } + + return result; +} + +static int decode_histogram_data_point_list(struct cmt *cmt, + struct cmt_map *map, + size_t data_point_count, + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint **data_point_list) +{ + size_t index; + int result; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + for (index = 0 ; + result == 0 && + index < data_point_count ; index++) { + result = decode_histogram_data_point(cmt, map, data_point_list[index]); + } + + return result; +} + +static int decode_counter_entry(struct cmt *cmt, + void *instance, + Opentelemetry__Proto__Metrics__V1__Sum *metric) +{ + struct cmt_counter *counter; + int result; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + counter = (struct cmt_counter *) instance; + + counter->map->metric_static_set = 0; + + result = decode_numerical_data_point_list(cmt, + counter->map, + metric->n_data_points, + metric->data_points); + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_DELTA) { + counter->aggregation_type = CMT_AGGREGATION_TYPE_DELTA; + } + else if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_CUMULATIVE) { + counter->aggregation_type = CMT_AGGREGATION_TYPE_CUMULATIVE; + } + else { + counter->aggregation_type = CMT_AGGREGATION_TYPE_UNSPECIFIED; + } + + counter->allow_reset = !metric->is_monotonic; + } + + return result; +} + +static int decode_gauge_entry(struct cmt *cmt, + void *instance, + Opentelemetry__Proto__Metrics__V1__Gauge *metric) +{ + struct cmt_gauge *gauge; + int result; + + gauge = (struct cmt_gauge *) instance; + + gauge->map->metric_static_set = 0; + + result = decode_numerical_data_point_list(cmt, + gauge->map, + metric->n_data_points, + metric->data_points); + + return result; +} + +static int decode_summary_entry(struct cmt *cmt, + void *instance, + Opentelemetry__Proto__Metrics__V1__Summary *metric) +{ + struct cmt_summary *summary; + int result; + + summary = (struct cmt_summary *) instance; + + if (summary->quantiles != NULL) { + free(summary->quantiles); + } + + summary->quantiles = NULL; + summary->quantiles_count = 0; + summary->map->metric_static_set = 0; + + result = decode_summary_data_point_list(cmt, + summary->map, + metric->n_data_points, + metric->data_points); + + return result; +} + +static int decode_histogram_entry(struct cmt *cmt, + void *instance, + Opentelemetry__Proto__Metrics__V1__Histogram *metric) +{ + struct cmt_histogram *histogram; + int result; + + histogram = (struct cmt_histogram *) instance; + + histogram->buckets = NULL; + histogram->map->metric_static_set = 0; + + result = decode_histogram_data_point_list(cmt, + histogram->map, + metric->n_data_points, + metric->data_points); + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_DELTA) { + histogram->aggregation_type = CMT_AGGREGATION_TYPE_DELTA; + } + else if (metric->aggregation_temporality == OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_CUMULATIVE) { + histogram->aggregation_type = CMT_AGGREGATION_TYPE_CUMULATIVE; + } + else { + histogram->aggregation_type = CMT_AGGREGATION_TYPE_UNSPECIFIED; + } + } + + return result; +} + +static int decode_metrics_entry(struct cmt *cmt, + Opentelemetry__Proto__Metrics__V1__Metric *metric) +{ + char *metric_description; + char *metric_namespace; + char *metric_subsystem; + char *metric_name; + void *instance; + int result; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + metric_name = metric->name; + metric_namespace = ""; + metric_subsystem = ""; + metric_description = metric->description; + + if (metric_description == NULL) { + metric_description = "-"; + } + else if (strlen(metric_description) == 0) { + metric_description = "-"; + } + + if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUM) { + instance = cmt_counter_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + 0, NULL); + + if (instance == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + result = decode_counter_entry(cmt, instance, metric->sum); + + if (result) { + cmt_counter_destroy(instance); + } + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_GAUGE) { + instance = cmt_gauge_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + 0, NULL); + + if (instance == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + result = decode_gauge_entry(cmt, instance, metric->gauge); + + if (result) { + cmt_gauge_destroy(instance); + } + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUMMARY) { + instance = cmt_summary_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + 1, (double []) { 0.0 }, + 0, NULL); + + if (instance == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + /* We are forced to create at least one quantile by the constructor but we + * don't know the details about it at the moment so we just leave it "open" + */ + + result = decode_summary_entry(cmt, instance, metric->summary); + + if (result) { + cmt_summary_destroy(instance); + } + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_HISTOGRAM) { + instance = cmt_histogram_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + (struct cmt_histogram_buckets *) cmt, + 0, NULL); + + if (instance == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + result = decode_histogram_entry(cmt, instance, metric->histogram); + + if (result) { + cmt_histogram_destroy(instance); + } + } + + return result; +} + +static int decode_scope_metadata_and_attributes(struct cfl_kvlist *external_metadata, + Opentelemetry__Proto__Common__V1__InstrumentationScope *scope) +{ + struct cfl_kvlist *attributes; + struct cfl_kvlist *metadata; + int result; + size_t index; + struct cfl_kvlist *root; + + root = get_or_create_external_metadata_kvlist(external_metadata, "scope"); + + if (root == NULL) { + return -1; + } + + metadata = get_or_create_external_metadata_kvlist(root, "metadata"); + + if (metadata == NULL) { + return -2; + } + + attributes = get_or_create_external_metadata_kvlist(root, "attributes"); + + if (attributes == NULL) { + return -3; + } + + if (scope == NULL) { + return 0; + } + + if (scope->name != NULL) { + result = cfl_kvlist_insert_string(metadata, "name", scope->name); + + if (result != 0) { + return -4; + } + } + + if (scope->version != NULL) { + result = cfl_kvlist_insert_string(metadata, "version", scope->version); + + if (result != 0) { + return -5; + } + } + + result = cfl_kvlist_insert_int64(metadata, "dropped_attributes_count", scope->dropped_attributes_count); + + if (result != 0) { + return -6; + } + + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < scope->n_attributes ; + index++) { + result = clone_kvlist_entry(attributes, + scope->attributes[index]); + } + + if (result != 0) { + return -7; + } + + return 0; +} + +static int decode_scope_metrics_metadata(struct cfl_kvlist *external_metadata, + Opentelemetry__Proto__Metrics__V1__ScopeMetrics *scope_metrics) +{ + struct cfl_kvlist *scope_metrics_metadata; + struct cfl_kvlist *scope_metrics_root; + int result; + + scope_metrics_root = get_or_create_external_metadata_kvlist(external_metadata, "scope_metrics"); + + if (scope_metrics_root == NULL) { + return -1; + } + + scope_metrics_metadata = get_or_create_external_metadata_kvlist(scope_metrics_root, "metadata"); + + if (scope_metrics_metadata == NULL) { + return -2; + } + + if (scope_metrics == NULL) { + return 0; + } + + if (scope_metrics->schema_url != NULL) { + result = cfl_kvlist_insert_string(scope_metrics_metadata, "schema_url", scope_metrics->schema_url); + + if (result != 0) { + return -3; + } + } + + return 0; +} + +static int decode_scope_metrics_entry(struct cfl_list *context_list, + Opentelemetry__Proto__Metrics__V1__ScopeMetrics *metrics) +{ + struct cmt *context; + int result; + size_t index; + + context = cmt_create(); + + if (context == NULL) { + return CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + cfl_list_add(&context->_head, context_list); + + result = cfl_kvlist_insert_string(context->internal_metadata, + "producer", + "opentelemetry"); + + if (result != 0) { + result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + result = decode_scope_metadata_and_attributes(context->external_metadata, + metrics->scope); + + if (result != 0) { + result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + } + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + result = decode_scope_metrics_metadata(context->external_metadata, + metrics); + + if (result != 0) { + result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + } + + if (result != CMT_DECODE_OPENTELEMETRY_SUCCESS) { + return result; + } + + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < metrics->n_metrics ; + index++) { + result = decode_metrics_entry(context, + metrics->metrics[index]); + } + + return result; +} + + +static int decode_resource_metadata_and_attributes(struct cfl_kvlist *external_metadata, + Opentelemetry__Proto__Resource__V1__Resource *resource) +{ + struct cfl_kvlist *attributes; + struct cfl_kvlist *metadata; + int result; + size_t index; + struct cfl_kvlist *root; + + root = get_or_create_external_metadata_kvlist(external_metadata, "resource"); + + if (root == NULL) { + return -1; + } + + metadata = get_or_create_external_metadata_kvlist(root, "metadata"); + + if (metadata == NULL) { + return -2; + } + + attributes = get_or_create_external_metadata_kvlist(root, "attributes"); + + if (attributes == NULL) { + return -3; + } + + if (resource == NULL) { + return 0; + } + + result = cfl_kvlist_insert_int64(metadata, "dropped_attributes_count", (int64_t) resource->dropped_attributes_count); + + if (result != 0) { + return -4; + } + + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < resource->n_attributes ; + index++) { + result = clone_kvlist_entry(attributes, + resource->attributes[index]); + } + + if (result != CMT_DECODE_OPENTELEMETRY_SUCCESS) { + return -5; + } + + return 0; +} + +static int decode_resource_metrics_metadata(struct cfl_kvlist *external_metadata, + Opentelemetry__Proto__Metrics__V1__ResourceMetrics *resource_metrics) +{ + struct cfl_kvlist *resource_metrics_metadata; + struct cfl_kvlist *resource_metrics_root; + int result; + + resource_metrics_root = get_or_create_external_metadata_kvlist(external_metadata, "resource_metrics"); + + if (resource_metrics_root == NULL) { + return -1; + } + + resource_metrics_metadata = get_or_create_external_metadata_kvlist(resource_metrics_root, "metadata"); + + if (resource_metrics_metadata == NULL) { + return -2; + } + + if (resource_metrics == NULL) { + return 0; + } + + if (resource_metrics->schema_url != NULL) { + result = cfl_kvlist_insert_string(resource_metrics_metadata, "schema_url", resource_metrics->schema_url); + + if (result != 0) { + return -3; + } + } + + return 0; +} + +static int decode_resource_metrics_entry( + struct cfl_list *context_list, + Opentelemetry__Proto__Metrics__V1__ResourceMetrics *resource_metrics) +{ + struct cmt *context; + int result; + size_t index; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < resource_metrics->n_scope_metrics ; + index++) { + result = decode_scope_metrics_entry(context_list, + resource_metrics->scope_metrics[index]); + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + context = cfl_list_entry_last(context_list, struct cmt, _head); + + if (context != NULL) { + if (resource_metrics->resource != NULL) { + result = decode_resource_metadata_and_attributes(context->external_metadata, + resource_metrics->resource); + + if (result != 0) { + result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + } + + if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { + result = decode_resource_metrics_metadata(context->external_metadata, + resource_metrics); + + if (result != 0) { + result = CMT_DECODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + } + } + } + } + + return result; +} + +static void destroy_context_list(struct cfl_list *context_list) +{ + struct cfl_list *iterator; + struct cmt *context; + struct cfl_list *tmp; + + cfl_list_foreach_safe(iterator, tmp, context_list) { + context = cfl_list_entry(iterator, struct cmt, _head); + + cfl_list_del(&context->_head); + + cmt_destroy(context); + } +} + +static int decode_service_request(struct cfl_list *context_list, + Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *service_request) +{ + int result; + size_t index; + + result = CMT_DECODE_OPENTELEMETRY_SUCCESS; + + if (service_request->n_resource_metrics > 0) { + for (index = 0 ; + result == CMT_DECODE_OPENTELEMETRY_SUCCESS && + index < service_request->n_resource_metrics ; + index++) { + + result = decode_resource_metrics_entry(context_list, + service_request->resource_metrics[index]); + } + } + + return result; +} + +int cmt_decode_opentelemetry_create(struct cfl_list *result_context_list, + char *in_buf, size_t in_size, + size_t *offset) +{ + Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *service_request; + int result; + + result = CMT_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; + + cfl_list_init(result_context_list); + + service_request = opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__unpack(NULL, in_size - *offset, + (unsigned char *) &in_buf[*offset]); + + if (service_request != NULL) { + result = decode_service_request(result_context_list, service_request); + + opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__free_unpacked(service_request, NULL); + } + + if (result != CMT_DECODE_OPENTELEMETRY_SUCCESS) { + destroy_context_list(result_context_list); + } + + return result; +} + +void cmt_decode_opentelemetry_destroy(struct cfl_list *context_list) +{ + if (context_list != NULL) { + destroy_context_list(context_list); + } +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.c b/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.c new file mode 100644 index 00000000..e33a9ef1 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.c @@ -0,0 +1,1160 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <stdarg.h> +#include <stdint.h> + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_decode_prometheus.h> + +#include <cmt_decode_prometheus_parser.h> +#include <stdio.h> +#include <string.h> +#include <cmetrics/cmt_map.h> + +static void reset_context(struct cmt_decode_prometheus_context *context, + bool reset_summary) +{ + int i; + struct cmt_decode_prometheus_context_sample *sample; + + while (!cfl_list_is_empty(&context->metric.samples)) { + sample = cfl_list_entry_first(&context->metric.samples, + struct cmt_decode_prometheus_context_sample, _head); + for (i = 0; i < context->metric.label_count; i++) { + cfl_sds_destroy(sample->label_values[i]); + } + cfl_list_del(&sample->_head); + free(sample); + } + + for (i = 0; i < context->metric.label_count; i++) { + cfl_sds_destroy(context->metric.labels[i]); + } + + if (context->metric.ns) { + if (strcmp(context->metric.ns, "")) { + /* when namespace is empty, "name" contains a pointer to the + * allocated string */ + free(context->metric.ns); + } + else { + free(context->metric.name); + } + } + + cfl_sds_destroy(context->strbuf); + context->strbuf = NULL; + if (reset_summary) { + context->current.summary = NULL; + } + cfl_sds_destroy(context->metric.name_orig); + cfl_sds_destroy(context->metric.docstring); + memset(&context->metric, + 0, + sizeof(struct cmt_decode_prometheus_context_metric)); + cfl_list_init(&context->metric.samples); +} + + +int cmt_decode_prometheus_create( + struct cmt **out_cmt, + const char *in_buf, + size_t in_size, + struct cmt_decode_prometheus_parse_opts *opts) +{ + yyscan_t scanner; + YY_BUFFER_STATE buf; + struct cmt *cmt; + struct cmt_decode_prometheus_context context; + int result; + + cmt = cmt_create(); + + if (cmt == NULL) { + return CMT_DECODE_PROMETHEUS_ALLOCATION_ERROR; + } + + memset(&context, 0, sizeof(context)); + context.cmt = cmt; + if (opts) { + context.opts = *opts; + } + cfl_list_init(&(context.metric.samples)); + cmt_decode_prometheus_lex_init(&scanner); + if (!in_size) { + in_size = strlen(in_buf); + } + buf = cmt_decode_prometheus__scan_bytes((char *)in_buf, in_size, scanner); + if (!buf) { + cmt_destroy(cmt); + return CMT_DECODE_PROMETHEUS_ALLOCATION_ERROR; + } + + result = cmt_decode_prometheus_parse(scanner, &context); + + if (result == 0) { + *out_cmt = cmt; + } + else { + cmt_destroy(cmt); + if (context.errcode) { + result = context.errcode; + } + reset_context(&context, true); + } + + cmt_decode_prometheus__delete_buffer(buf, scanner); + cmt_decode_prometheus_lex_destroy(scanner); + + return result; +} + +void cmt_decode_prometheus_destroy(struct cmt *cmt) +{ + cmt_destroy(cmt); +} + +static int report_error(struct cmt_decode_prometheus_context *context, + int errcode, + const char *format, ...) +{ + va_list args; + va_start(args, format); + context->errcode = errcode; + if (context->opts.errbuf && context->opts.errbuf_size) { + vsnprintf(context->opts.errbuf, context->opts.errbuf_size - 1, format, args); + } + va_end(args); + return errcode; +} + +static int split_metric_name(struct cmt_decode_prometheus_context *context, + cfl_sds_t metric_name, char **ns, + char **subsystem, char **name) +{ + /* split the name */ + *ns = strdup(metric_name); + if (!*ns) { + return report_error(context, + CMT_DECODE_PROMETHEUS_ALLOCATION_ERROR, + "memory allocation failed"); + } + *subsystem = strchr(*ns, '_'); + if (!(*subsystem)) { + *name = *ns; + *ns = ""; + } + else { + **subsystem = 0; /* split */ + (*subsystem)++; + *name = strchr(*subsystem, '_'); + if (!(*name)) { + *name = *subsystem; + *subsystem = ""; + } + else { + **name = 0; + (*name)++; + } + } + return 0; +} + +/* Use this helper function to return a stub value for docstring when it is not + * available. This is necessary for now because the metric constructors require + * a docstring, even though it is not required by prometheus spec. */ +static char *get_docstring(struct cmt_decode_prometheus_context *context) +{ + return context->metric.docstring && strlen(context->metric.docstring) ? + context->metric.docstring : " "; +} + +static int parse_uint64(const char *in, uint64_t *out) +{ + char *end; + int64_t val; + + errno = 0; + val = strtol(in, &end, 10); + if (end == in || *end != 0 || errno) { + return -1; + } + + /* Even though prometheus text format supports negative numbers, cmetrics + * doesn't, so we truncate to 0 */ + if (val < 0) { + val = 0; + } + *out = val; + return 0; +} + +static int parse_double(const char *in, double *out) +{ + char *end; + double val; + errno = 0; + val = strtod(in, &end); + if (end == in || *end != 0 || errno) { + return -1; + } + *out = val; + return 0; +} + +static int parse_timestamp(struct cmt_decode_prometheus_context *context, + char *data_source, uint64_t *timestamp) +{ + int result; + + result = CMT_DECODE_PROMETHEUS_SUCCESS; + + if (data_source != NULL && strlen(data_source) > 0) { + result = parse_uint64(data_source, timestamp); + + if (result) { + result = report_error(context, + CMT_DECODE_PROMETHEUS_PARSE_TIMESTAMP_FAILED, + "failed to parse sample: \"%s\" is not a valid " + "timestamp", data_source); + } + else { + /* prometheus text format timestamps are expressed in milliseconds, + * while cmetrics expresses them in nanoseconds, so multiply by 10e5 + */ + + *timestamp *= 10e5; + } + } + + return result; +} + +static int parse_value_timestamp( + struct cmt_decode_prometheus_context *context, + struct cmt_decode_prometheus_context_sample *sample, + double *value, + uint64_t *timestamp) +{ + + if (parse_double(sample->value1, value)) { + return report_error(context, + CMT_DECODE_PROMETHEUS_PARSE_VALUE_FAILED, + "failed to parse sample: \"%s\" is not a valid " + "value", sample->value1); + } + + if (context->opts.override_timestamp) { + *timestamp = context->opts.override_timestamp; + } + else if (!strlen(sample->value2)) { + /* No timestamp was specified, use default value */ + *timestamp = context->opts.default_timestamp; + return 0; + } + else if (parse_uint64(sample->value2, timestamp)) { + return report_error(context, + CMT_DECODE_PROMETHEUS_PARSE_TIMESTAMP_FAILED, + "failed to parse sample: \"%s\" is not a valid " + "timestamp", sample->value2); + } + + /* prometheus text format timestamps are in milliseconds, while cmetrics is in + * nanoseconds, so multiply by 10e5 */ + *timestamp = *timestamp * 10e5; + + return 0; +} + +static int add_metric_counter(struct cmt_decode_prometheus_context *context) +{ + int ret; + size_t label_count; + struct cmt_counter *c; + struct cfl_list *head; + struct cfl_list *tmp; + struct cmt_decode_prometheus_context_sample *sample; + double value; + uint64_t timestamp; + + c = cmt_counter_create(context->cmt, + context->metric.ns, + context->metric.subsystem, + context->metric.name, + get_docstring(context), + context->metric.label_count, + context->metric.labels); + + if (!c) { + return report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_counter_create failed"); + } + + cfl_list_foreach_safe(head, tmp, &context->metric.samples) { + sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); + label_count = context->metric.label_count; + ret = parse_value_timestamp(context, sample, &value, ×tamp); + if (ret) { + return ret; + } + if (cmt_counter_set(c, + timestamp, + value, + label_count, + label_count ? sample->label_values : NULL)) { + return report_error(context, + CMT_DECODE_PROMETHEUS_CMT_SET_ERROR, + "cmt_counter_set failed"); + } + } + + return 0; +} + +static int add_metric_gauge(struct cmt_decode_prometheus_context *context) +{ + int ret; + size_t label_count; + struct cmt_gauge *c; + struct cfl_list *head; + struct cfl_list *tmp; + struct cmt_decode_prometheus_context_sample *sample; + double value; + uint64_t timestamp; + + c = cmt_gauge_create(context->cmt, + context->metric.ns, + context->metric.subsystem, + context->metric.name, + get_docstring(context), + context->metric.label_count, + context->metric.labels); + + if (!c) { + return report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_gauge_create failed"); + } + + cfl_list_foreach_safe(head, tmp, &context->metric.samples) { + sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); + label_count = context->metric.label_count; + ret = parse_value_timestamp(context, sample, &value, ×tamp); + if (ret) { + return ret; + } + if (cmt_gauge_set(c, + timestamp, + value, + label_count, + label_count ? sample->label_values : NULL)) { + return report_error(context, + CMT_DECODE_PROMETHEUS_CMT_SET_ERROR, + "cmt_gauge_set failed"); + } + } + + return 0; +} + +static int add_metric_untyped(struct cmt_decode_prometheus_context *context) +{ + int ret; + size_t label_count; + struct cmt_untyped *c; + struct cfl_list *head; + struct cfl_list *tmp; + struct cmt_decode_prometheus_context_sample *sample; + double value; + uint64_t timestamp; + + c = cmt_untyped_create(context->cmt, + context->metric.ns, + context->metric.subsystem, + context->metric.name, + get_docstring(context), + context->metric.label_count, + context->metric.labels); + + if (!c) { + return report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_untyped_create failed"); + } + + cfl_list_foreach_safe(head, tmp, &context->metric.samples) { + sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); + label_count = context->metric.label_count; + ret = parse_value_timestamp(context, sample, &value, ×tamp); + if (ret) { + return ret; + } + if (cmt_untyped_set(c, + timestamp, + value, + label_count, + label_count ? sample->label_values : NULL)) { + return report_error(context, + CMT_DECODE_PROMETHEUS_CMT_SET_ERROR, + "cmt_untyped_set failed"); + } + } + + return 0; +} + +static int add_metric_histogram(struct cmt_decode_prometheus_context *context) +{ + int ret = 0; + int i; + size_t bucket_count; + size_t bucket_index; + double *buckets = NULL; + uint64_t *bucket_defaults = NULL; + double sum; + uint64_t count = 0; + double count_dbl; + struct cfl_list *head; + struct cfl_list *tmp; + struct cmt_decode_prometheus_context_sample *sample; + size_t le_label_index = 0; + struct cmt_histogram *h; + struct cmt_histogram_buckets *cmt_buckets; + cfl_sds_t *labels_without_le = NULL; + cfl_sds_t *values_without_le = NULL; + int label_i; + uint64_t timestamp; + + /* bucket_count = sample count - 3: + * - "Inf" bucket + * - sum + * - count */ + bucket_count = cfl_list_size(&context->metric.samples) - 3; + timestamp = context->opts.override_timestamp; + + bucket_defaults = calloc(bucket_count + 1, sizeof(*bucket_defaults)); + if (!bucket_defaults) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate bucket defaults"); + goto end; + } + buckets = calloc(bucket_count, sizeof(*buckets)); + if (!buckets) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate buckets"); + goto end; + } + labels_without_le = calloc(context->metric.label_count - 1, sizeof(*labels_without_le)); + if (!labels_without_le) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate labels_without_le"); + goto end; + } + values_without_le = calloc(context->metric.label_count - 1, sizeof(*labels_without_le)); + if (!values_without_le) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate values_without_le"); + goto end; + } + + + label_i = 0; + sample = cfl_list_entry_first(&context->metric.samples, struct cmt_decode_prometheus_context_sample, _head); + for (i = 0; i < context->metric.label_count; i++) { + if (!strcmp(context->metric.labels[i], "le")) { + le_label_index = i; + } else { + labels_without_le[label_i] = context->metric.labels[i]; + values_without_le[label_i] = sample->label_values[i]; + label_i++; + } + } + + bucket_index = 0; + cfl_list_foreach_safe(head, tmp, &context->metric.samples) { + sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); + switch (sample->type) { + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_BUCKET: + if (bucket_index == bucket_count) { + /* probably last bucket, which has "Inf" */ + break; + } + if (parse_double(sample->label_values[le_label_index], + buckets + bucket_index)) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse bucket"); + goto end; + } + if (parse_uint64(sample->value1, + bucket_defaults + bucket_index)) { + /* Count is supposed to be integer, but apparently + * some tools can generate count in a floating format. + * Try to parse as a double and then cast to uint64_t */ + if (parse_double(sample->value1, &count_dbl) || count_dbl < 0) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse count"); + goto end; + } else { + *(bucket_defaults + bucket_index) = (uint64_t)count_dbl; + } + } + bucket_index++; + + if (!timestamp) { + ret = parse_timestamp(context, sample->value2, ×tamp); + + if (ret) { + goto end; + } + } + + break; + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_SUM: + if (parse_double(sample->value1, &sum)) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse sum"); + goto end; + } + + if (!timestamp) { + ret = parse_timestamp(context, sample->value2, ×tamp); + + if (ret) { + goto end; + } + } + + break; + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_COUNT: + if (parse_uint64(sample->value1, &count)) { + /* Count is supposed to be integer, but apparently + * some tools can generate count in a floating format. + * Try to parse as a double and then cast to uint64_t */ + if (parse_double(sample->value1, &count_dbl) || count_dbl < 0) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse count"); + goto end; + } else { + count = (uint64_t)count_dbl; + } + } + bucket_defaults[bucket_index] = count; + + if (!timestamp) { + ret = parse_timestamp(context, sample->value2, ×tamp); + + if (ret) { + goto end; + } + } + + break; + } + } + + if (!timestamp) { + /* No timestamp was specified, use default value */ + timestamp = context->opts.default_timestamp; + } + + h = context->current.histogram; + if (!h || label_i != h->map->label_count) { + cmt_buckets = cmt_histogram_buckets_create_size(buckets, bucket_count); + if (!cmt_buckets) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_histogram_buckets_create_size failed"); + goto end; + } + + h = cmt_histogram_create(context->cmt, + context->metric.ns, + context->metric.subsystem, + context->metric.name, + get_docstring(context), + cmt_buckets, + label_i, + label_i ? labels_without_le : NULL); + + if (!h) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_histogram_create failed"); + goto end; + } + + context->current.histogram = h; + } + + if (cmt_histogram_set_default(h, timestamp, bucket_defaults, sum, count, + label_i, + label_i ? values_without_le : NULL)) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_histogram_set_default failed"); + } + + +end: + if (buckets) { + free(buckets); + } + if (bucket_defaults) { + free(bucket_defaults); + } + if (labels_without_le) { + free(labels_without_le); + } + if (values_without_le) { + free(values_without_le); + } + + return ret; +} + +static int add_metric_summary(struct cmt_decode_prometheus_context *context) +{ + int ret = 0; + int i; + size_t quantile_count; + size_t quantile_index; + double *quantiles = NULL; + double *quantile_defaults = NULL; + double sum; + double count_dbl; + size_t label_count; + uint64_t count = 0; + struct cfl_list *head; + struct cfl_list *tmp; + struct cmt_decode_prometheus_context_sample *sample; + size_t quantile_label_index = 0; + struct cmt_summary *s; + cfl_sds_t *labels_without_quantile = NULL; + cfl_sds_t *values_without_quantile = NULL; + int label_i; + uint64_t timestamp; + + /* quantile_count = sample count - 2: + * - sum + * - count */ + quantile_count = cfl_list_size(&context->metric.samples) - 2; + timestamp = context->opts.override_timestamp; + + quantile_defaults = calloc(quantile_count, sizeof(*quantile_defaults)); + if (!quantile_defaults) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate quantile defaults"); + goto end; + } + quantiles = calloc(quantile_count, sizeof(*quantiles)); + if (!quantiles) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate quantiles"); + goto end; + } + + label_count = 0; + for (i = 0; i < context->metric.label_count; i++) { + if (strcmp(context->metric.labels[i], "quantile")) { + /* quantile is not a label */ + label_count++; + } + } + + labels_without_quantile = calloc(label_count, sizeof(*labels_without_quantile)); + if (!labels_without_quantile) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate labels_without_quantile"); + goto end; + } + values_without_quantile = calloc(label_count, sizeof(*labels_without_quantile)); + if (!values_without_quantile) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to allocate values_without_quantile"); + goto end; + } + + label_i = 0; + sample = cfl_list_entry_first(&context->metric.samples, + struct cmt_decode_prometheus_context_sample, _head); + for (i = 0; i < context->metric.label_count; i++) { + if (!strcmp(context->metric.labels[i], "quantile")) { + quantile_label_index = i; + break; + } else { + labels_without_quantile[label_i] = context->metric.labels[i]; + values_without_quantile[label_i] = sample->label_values[i]; + label_i++; + } + } + + quantile_index = 0; + cfl_list_foreach_safe(head, tmp, &context->metric.samples) { + sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); + switch (sample->type) { + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_NORMAL: + if (parse_double(sample->label_values[quantile_label_index], + quantiles + quantile_index)) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse bucket"); + goto end; + } + if (parse_double(sample->value1, + quantile_defaults + quantile_index)) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse quantile value"); + goto end; + } + quantile_index++; + + if (!timestamp) { + ret = parse_timestamp(context, sample->value2, ×tamp); + + if (ret) { + goto end; + } + } + + break; + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_SUM: + if (parse_double(sample->value1, &sum)) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse summary sum"); + goto end; + } + + if (!timestamp) { + ret = parse_timestamp(context, sample->value2, ×tamp); + + if (ret) { + goto end; + } + } + + break; + + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_COUNT: + if (parse_uint64(sample->value1, &count)) { + /* Count is supposed to be integer, but apparently + * some tools can generate count in a floating format. + * Try to parse as a double and then cast to uint64_t */ + if (parse_double(sample->value1, &count_dbl) || count_dbl < 0) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "failed to parse count"); + goto end; + } else { + count = (uint64_t)count_dbl; + } + } + + if (!timestamp) { + ret = parse_timestamp(context, sample->value2, ×tamp); + + if (ret) { + goto end; + } + } + + break; + } + } + + if (!timestamp) { + /* No timestamp was specified, use default value */ + timestamp = context->opts.default_timestamp; + } + + s = context->current.summary; + if (!s || label_i != s->map->label_count) { + s = cmt_summary_create(context->cmt, + context->metric.ns, + context->metric.subsystem, + context->metric.name, + get_docstring(context), + quantile_count, + quantiles, + label_i, + label_i ? labels_without_quantile : NULL); + + if (!s) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_summary_create failed"); + goto end; + } + + context->current.summary = s; + } + + if (cmt_summary_set_default(s, timestamp, quantile_defaults, sum, count, + label_i, + label_i ? values_without_quantile : NULL)) { + ret = report_error(context, + CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, + "cmt_summary_set_default failed"); + } + + +end: + if (quantile_defaults) { + free(quantile_defaults); + } + if (quantiles) { + free(quantiles); + } + if (labels_without_quantile) { + free(labels_without_quantile); + } + if (values_without_quantile) { + free(values_without_quantile); + } + + return ret; +} + +static int finish_metric(struct cmt_decode_prometheus_context *context, + bool reset_summary, + cfl_sds_t current_metric_name) +{ + int rv = 0; + + if (cfl_list_is_empty(&context->metric.samples)) { + goto end; + } + + switch (context->metric.type) { + case COUNTER: + rv = add_metric_counter(context); + break; + case GAUGE: + rv = add_metric_gauge(context); + break; + case HISTOGRAM: + rv = add_metric_histogram(context); + break; + case SUMMARY: + rv = add_metric_summary(context); + break; + default: + rv = add_metric_untyped(context); + break; + } + +end: + reset_context(context, reset_summary); + + if (current_metric_name) { + context->metric.name_orig = current_metric_name; + rv = split_metric_name(context, + current_metric_name, + &(context->metric.ns), + &(context->metric.subsystem), + &(context->metric.name)); + } + return rv; +} + +/* special case for summary */ +static int finish_duplicate_histogram_summary_sum_count( + struct cmt_decode_prometheus_context *context, + cfl_sds_t metric_name, + int type) +{ + int rv; + int current_metric_type; + cfl_sds_t current_metric_docstring; + + if (type == CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_COUNT) { + cfl_sds_set_len(metric_name, cfl_sds_len(metric_name) - 6); + } else if (type == CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_SUM) { + cfl_sds_set_len(metric_name, cfl_sds_len(metric_name) - 4); + } else if (type == CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_BUCKET) { + cfl_sds_set_len(metric_name, cfl_sds_len(metric_name) - 7); + } + metric_name[cfl_sds_len(metric_name)] = 0; + + current_metric_type = context->metric.type; + current_metric_docstring = cfl_sds_create(context->metric.docstring); + + rv = finish_metric(context, false, metric_name); + if (rv) { + cfl_sds_destroy(current_metric_docstring); + return rv; + } + + context->metric.type = current_metric_type; + context->metric.docstring = current_metric_docstring; + context->metric.current_sample_type = type; + + return 0; +} + +static int parse_histogram_summary_name( + struct cmt_decode_prometheus_context *context, + cfl_sds_t metric_name) +{ + bool sum_found; + bool count_found; + bool has_buckets; + bool is_previous_sum_or_count; + bool name_matched = false; + struct cfl_list *head; + struct cfl_list *tmp; + size_t current_name_len; + size_t parsed_name_len; + struct cmt_decode_prometheus_context_sample *sample; + + current_name_len = strlen(metric_name); + parsed_name_len = strlen(context->metric.name_orig); + if (current_name_len < parsed_name_len) { + /* current name length cannot be less than the length already parsed. That means + * another metric has started */ + return finish_metric(context, true, metric_name); + } + + if (strncmp(context->metric.name_orig, metric_name, parsed_name_len)) { + /* the name prefix must be the same or we are starting a new metric */ + return finish_metric(context, true, metric_name); + } + else if (parsed_name_len == current_name_len) { + name_matched = true; + } + + sum_found = false; + count_found = false; + has_buckets = false; + + cfl_list_foreach_safe(head, tmp, &context->metric.samples) { + sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); + + switch (sample->type) { + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_SUM: + sum_found = true; + break; + case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_COUNT: + count_found = true; + break; + default: + has_buckets = true; + break; + } + } + + sample = cfl_list_entry_last(&context->metric.samples, + struct cmt_decode_prometheus_context_sample, _head); + is_previous_sum_or_count = sample->type == CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_SUM || + sample->type == CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_COUNT; + + if (name_matched) { + if (sum_found && count_found) { + /* finish instance of the summary/histogram */ + return finish_duplicate_histogram_summary_sum_count(context, metric_name, -1); + } + else { + /* parsing HELP after TYPE */ + cfl_sds_destroy(metric_name); + return 0; + } + } + + /* invalid histogram/summary suffix, treat it as a different metric */ + if (!strcmp(metric_name + parsed_name_len, "_bucket")) { + if (sum_found && count_found && has_buckets && is_previous_sum_or_count) { + /* already found both sum and count, so this is a new metric */ + return finish_duplicate_histogram_summary_sum_count( + context, + metric_name, + CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_BUCKET); + } + context->metric.current_sample_type = CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_BUCKET; + } + else if (!strcmp(metric_name + parsed_name_len, "_sum")) { + if (sum_found) { + /* already found a `_sum` for this metric, so this must necessarily be a new + * one */ + return finish_duplicate_histogram_summary_sum_count( + context, + metric_name, + CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_SUM); + } + context->metric.current_sample_type = CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_SUM; + sum_found = true; + } + else if (!strcmp(metric_name + parsed_name_len, "_count")) { + if (count_found) { + /* already found a `_count` for this metric, so this must necessarily be a new + * one */ + return finish_duplicate_histogram_summary_sum_count( + context, + metric_name, + CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_COUNT); + } + context->metric.current_sample_type = CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_COUNT; + count_found = true; + } + else { + /* invalid histogram/summary suffix, treat it as a different metric */ + return finish_metric(context, true, metric_name); + } + + /* still in the same metric */ + cfl_sds_destroy(metric_name); + return 0; +} + +static int parse_metric_name( + struct cmt_decode_prometheus_context *context, + cfl_sds_t metric_name) +{ + int ret = 0; + + if (context->metric.name_orig) { + if (context->metric.type == HISTOGRAM || context->metric.type == SUMMARY) { + ret = parse_histogram_summary_name(context, metric_name); + if (!ret) { + /* bucket/sum/count parsed */ + return ret; + } + } + else if (strcmp(context->metric.name_orig, metric_name)) { + /* new metric name means the current metric is finished */ + return finish_metric(context, true, metric_name); + } + else { + /* same metric with name already allocated, destroy and return */ + cfl_sds_destroy(metric_name); + return ret; + } + } + + if (!ret) { + context->metric.name_orig = metric_name; + ret = split_metric_name(context, metric_name, + &(context->metric.ns), + &(context->metric.subsystem), + &(context->metric.name)); + } + else { + cfl_sds_destroy(metric_name); + } + + return ret; +} + +static int parse_label( + struct cmt_decode_prometheus_context *context, + cfl_sds_t name, cfl_sds_t value) +{ + int i; + struct cmt_decode_prometheus_context_sample *sample; + + if (context->metric.label_count >= CMT_DECODE_PROMETHEUS_MAX_LABEL_COUNT) { + cfl_sds_destroy(name); + cfl_sds_destroy(value); + return report_error(context, + CMT_DECODE_PROMETHEUS_MAX_LABEL_COUNT_EXCEEDED, + "maximum number of labels exceeded"); + } + + /* check if the label is already registered */ + for (i = 0; i < context->metric.label_count; i++) { + if (!strcmp(name, context->metric.labels[i])) { + /* found, free the name memory and use the existing one */ + cfl_sds_destroy(name); + name = context->metric.labels[i]; + break; + } + } + if (i == context->metric.label_count) { + /* didn't found the label, add it now */ + context->metric.labels[i] = name; + context->metric.label_count++; + } + + sample = cfl_list_entry_last(&context->metric.samples, + struct cmt_decode_prometheus_context_sample, _head); + sample->label_values[i] = value; + return 0; +} + +static int sample_start(struct cmt_decode_prometheus_context *context) +{ + struct cmt_decode_prometheus_context_sample *sample; + + sample = malloc(sizeof(*sample)); + if (!sample) { + return report_error(context, + CMT_DECODE_PROMETHEUS_ALLOCATION_ERROR, + "memory allocation failed"); + } + + memset(sample, 0, sizeof(*sample)); + sample->type = context->metric.current_sample_type; + cfl_list_add(&sample->_head, &context->metric.samples); + return 0; +} + +static int parse_sample( + struct cmt_decode_prometheus_context *context, + const char *value1, + const char *value2) +{ + struct cmt_decode_prometheus_context_sample *sample; + sample = cfl_list_entry_last(&context->metric.samples, + struct cmt_decode_prometheus_context_sample, _head); + + strcpy(sample->value1, value1); + strcpy(sample->value2, value2); + return 0; +} + +/* called automatically by the generated parser code on error */ +static int cmt_decode_prometheus_error(void *yyscanner, + struct cmt_decode_prometheus_context *context, + const char *msg) +{ + report_error(context, CMT_DECODE_PROMETHEUS_SYNTAX_ERROR, msg); + return 0; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.l b/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.l new file mode 100644 index 00000000..54a7c79d --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.l @@ -0,0 +1,195 @@ +%option prefix="cmt_decode_prometheus_" + +%option reentrant bison-bridge +%option noyywrap nounput noinput +%option nodefault + +%{ + +#include <cmetrics/cmt_decode_prometheus.h> + +#define STRBUF_RET \ + yylval->str = context->strbuf; \ + context->strbuf = NULL + +%} + +/* here we define some states that allow us to create rules only + matched in certain situations */ + +%x INQUOTE HELPTAG INHELPTAG TYPETAG INTYPETAG COMMENT COMMENT_START + +%% + +%{ + if (context->opts.start_token) { + int t = context->opts.start_token; + context->opts.start_token = 0; + return t; + } +%} + +<*>\r\n|\n { + int top_state = YYSTATE; + // We always return to the INITIAL state on a linefeed, no matter which + // state we are on (the "<*>" means this rule is applied on every state) + BEGIN(INITIAL); + if (top_state == INHELPTAG) { + // But if we were on the INHELPTAG state, we return everything collected + // in strbuf + STRBUF_RET; + return METRIC_DOC; + } +} + +^[ ]*#[ ]* { + // Lines with "#" as the first non-whitespace character begin a comment + // unless the first token is either HELP or TYPE. To handle this ambiguity, + // we enter the COMMENT_START state, which contains rules for selecting + // if this is a HELP/TYPE tag or just a normal comment + BEGIN(COMMENT_START); +} + +<COMMENT_START>HELP[ \t]+ { + // Begin a help tag + BEGIN(HELPTAG); +} + +<COMMENT_START>TYPE[ \t]+ { + // Begin a type tag + BEGIN(TYPETAG); +} + +<COMMENT_START>[^\n] { + // Any character that is not a newline begins the COMMENT state where + // everything is ignored until the next linefeed. This works because flex + // will prioritize the two rules above this one since they have longer + // matches. + BEGIN(COMMENT); +} + +<COMMENT>[^\n]+ { + // ignore +} + +<HELPTAG,TYPETAG>[^ \t]+ { + // The next token will be the metric name + yylval->str = cfl_sds_create(yytext); + return YYSTATE == HELPTAG ? HELP : TYPE; +} + +<HELPTAG,TYPETAG>[ \t]* { + // Every whitespace after the metric name is ignored + if (YYSTATE == HELPTAG) { + // For HELPTAG we enter the INHELPTAG start condition which we will use to + // read everything until the end of line into context->strbuf. We enter a + // separate start condition for this to handle "\\" and "\n" escapes + // more easily. + BEGIN(INHELPTAG); + context->strbuf = sds_alloc(256); + } + else { + // For TYPETAG we enter INTYPETAG start condition to check only valid + // metric types are accepted. This prevents us from having to do + // manual validation later. + BEGIN(INTYPETAG); + } +} + +<INHELPTAG><<EOF>> { + // Handle EOF when in the INHELPTAG state by returning the buffered docstring. + // While this is not strictly necessary, it makes easier unit testing the + // lexer + BEGIN(INITIAL); + STRBUF_RET; + return METRIC_DOC; +} + +<INHELPTAG>\\n { + // Process linefeed escape sequence + context->strbuf = cfl_sds_cat(context->strbuf, "\n", 1); +} + +<INHELPTAG>\\\\ { + // Process backslack escape sequence + context->strbuf = cfl_sds_cat(context->strbuf, "\\", 1); +} + +<INHELPTAG>[^\r\n\\]+ { + // Put everything that is not a backslash or a line feed into strbuf + context->strbuf = cfl_sds_cat(context->strbuf, yytext, yyleng); +} + +<INTYPETAG>counter { + return COUNTER; +} + +<INTYPETAG>gauge { + return GAUGE; +} + +<INTYPETAG>summary { + return SUMMARY; +} + +<INTYPETAG>untyped { + return UNTYPED; +} + +<INTYPETAG>histogram { + return HISTOGRAM; +} + +<INTYPETAG,INITIAL>[ \t]+ { + /* ignore whitespace */ +} + +["] { + BEGIN(INQUOTE); + context->strbuf = sds_alloc(256); +} + +<INQUOTE>[\\]["] { + context->strbuf = cfl_sds_cat(context->strbuf, "\"", 1); +} + +<INQUOTE>\\n { + context->strbuf = cfl_sds_cat(context->strbuf, "\n", 1); +} + +<INQUOTE>\\\\ { + context->strbuf = cfl_sds_cat(context->strbuf, "\\", 1); +} + +<INQUOTE>[^\r\n\\"]+ { + context->strbuf = cfl_sds_cat(context->strbuf, yytext, yyleng); +} + +<INQUOTE>["] { + BEGIN(INITIAL); + STRBUF_RET; + return QUOTED; +} + +[+-]?(?i:(INF|NAN)) { + strncpy(yylval->numstr, yytext, sizeof(yylval->numstr) - 1); + return INFNAN; +} + +[a-zA-Z_][a-zA-Z_0-9]* { + yylval->str = cfl_sds_create(yytext); + return IDENTIFIER; +} + +[0-9.eE+-]+ { + strncpy(yylval->numstr, yytext, sizeof(yylval->numstr) - 1); + return NUMSTR; +} + +. { + // Catch all workaround to avoid having to define token types for every + // possible delimiter. We simply return the character to the parser. + return *yytext; +} + +%% diff --git a/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.y b/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.y new file mode 100644 index 00000000..d4396b9e --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.y @@ -0,0 +1,151 @@ +%define api.pure true +%name-prefix "cmt_decode_prometheus_" +%define parse.error verbose + +%param {void *yyscanner} +%param {struct cmt_decode_prometheus_context *context} + +%{ +// we inline cmt_decode_prometheus.c which contains all the actions to avoid +// having to export a bunch of symbols that are only used by the generated +// parser code +#include "cmt_decode_prometheus.c" +%} + +%union { + cfl_sds_t str; + char numstr[64]; + int integer; +} + +%token '=' '{' '}' ',' +%token <str> IDENTIFIER QUOTED HELP TYPE METRIC_DOC +%token COUNTER GAUGE SUMMARY UNTYPED HISTOGRAM +%token START_HEADER START_LABELS START_SAMPLES +%token <numstr> NUMSTR INFNAN + +%type <integer> metric_type +%type <numstr> value + +%destructor { + cfl_sds_destroy($$); +} <str> + +%start start; + +%% + +start: + START_HEADER header + | START_LABELS labels + | START_SAMPLES samples + | metrics { + if (finish_metric(context, true, NULL)) { + YYABORT; + } + } +; + +metrics: + metrics metric + | metric +; + +metric: + header samples + | samples + | header +; + +header: + help type + | help + | type help + | type +; + +help: + HELP METRIC_DOC { + if (parse_metric_name(context, $1)) { + YYABORT; + } + context->metric.docstring = $2; + } +; + +type: + TYPE metric_type { + if (parse_metric_name(context, $1)) { + YYABORT; + } + context->metric.type = $2; + } +; + +metric_type: + COUNTER { $$ = COUNTER; } + | GAUGE { $$ = GAUGE; } + | SUMMARY { $$ = SUMMARY; } + | UNTYPED { $$ = UNTYPED; } + | HISTOGRAM { $$ = HISTOGRAM; } +; + +samples: + samples sample + | sample +; + +sample: + IDENTIFIER { + if (parse_metric_name(context, $1)) { + YYABORT; + } + $1 = NULL; + if (sample_start(context)) { + YYABORT; + } + } sample_data +; + +sample_data: + '{' '}' values + | '{' labels '}' values + | values +; + +labels: + labellist ',' + | labellist +; + +labellist: + labellist ',' label + | label +; + +label: + IDENTIFIER '=' QUOTED { + if (parse_label(context, $1, $3)) { + YYABORT; + } + } +; + +values: + value value { + if (parse_sample(context, $1, $2)) { + YYABORT; + } + } + | value { + if (parse_sample(context, $1, "")) { + YYABORT; + } + } +; + +value: + NUMSTR | INFNAN +; + +%% diff --git a/fluent-bit/lib/cmetrics/src/cmt_encode_influx.c b/fluent-bit/lib/cmetrics/src/cmt_encode_influx.c new file mode 100644 index 00000000..1dfe3797 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_encode_influx.c @@ -0,0 +1,374 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_compat.h> + +#include <ctype.h> + +/* + * Influx wire protocol + * -------------------- + * https://docs.influxdata.com/influxdb/cloud/reference/syntax/line-protocol/ + * + * Format used by influxdb when ingesting prometheus metrics + * --------------------------------------------------------- + * https://docs.influxdata.com/influxdb/v2.1/reference/prometheus-metrics/ + */ + + +/* Histograms and Summaries : + * Just to get started I'll use version 1 which is what I think we have been + * following so far, if we were to use version 2 format_metric would need to be + * converted to call this function multiple times with a single limit on each line. + */ + +static void append_histogram_metric_value(struct cmt_map *map, + cfl_sds_t *buf, + struct cmt_metric *metric) +{ + size_t entry_buffer_length; + size_t entry_buffer_index; + char entry_buffer[256]; + struct cmt_histogram *histogram; + struct cmt_histogram_buckets *buckets; + size_t index; + + histogram = (struct cmt_histogram *) map->parent; + buckets = histogram->buckets; + + for (index = 0 ; index <= buckets->count ; index++) { + if (index < buckets->count) { + entry_buffer_index = snprintf(entry_buffer, + sizeof(entry_buffer) - 1, + "%g", + buckets->upper_bounds[index]); + } + else { + entry_buffer_index = snprintf(entry_buffer, + sizeof(entry_buffer) - 1, + "+Inf"); + } + + entry_buffer_length = entry_buffer_index; + + entry_buffer_length += snprintf(&entry_buffer[entry_buffer_index], + sizeof(entry_buffer) - 1 - + entry_buffer_index, + "=%" PRIu64 ",", + cmt_metric_hist_get_value(metric, + index)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + } + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "sum=%.17g,", + cmt_metric_hist_get_sum_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "count=%" PRIu64 " ", + cmt_metric_hist_get_count_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "%" PRIu64 "\n", + cmt_metric_get_timestamp(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); +} + +static void append_summary_metric_value(struct cmt_map *map, + cfl_sds_t *buf, + struct cmt_metric *metric) +{ + size_t entry_buffer_length; + char entry_buffer[256]; + struct cmt_summary *summary; + size_t index; + + summary = (struct cmt_summary *) map->parent; + + for (index = 0 ; index < summary->quantiles_count ; index++) { + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1, + "%g=%.17g,", + summary->quantiles[index], + cmt_summary_quantile_get_value(metric, + index)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + } + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "sum=%.17g,", + cmt_summary_get_sum_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "count=%" PRIu64 " ", + cmt_summary_get_count_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "%" PRIu64 "\n", + cmt_metric_get_timestamp(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); +} + +static void append_metric_value(struct cmt_map *map, + cfl_sds_t *buf, struct cmt_metric *metric) +{ + int len; + uint64_t ts; + double val; + char tmp[256]; + struct cmt_opts *opts; + + if (map->type == CMT_HISTOGRAM) { + return append_histogram_metric_value(map, buf, metric); + } + else if (map->type == CMT_SUMMARY) { + return append_summary_metric_value(map, buf, metric); + } + + opts = map->opts; + + /* Retrieve metric value */ + val = cmt_metric_get_value(metric); + + ts = cmt_metric_get_timestamp(metric); + len = snprintf(tmp, sizeof(tmp) - 1, "=%.17g %" PRIu64 "\n", val, ts); + + cfl_sds_cat_safe(buf, opts->name, cfl_sds_len(opts->name)); + cfl_sds_cat_safe(buf, tmp, len); + +} + +static int line_protocol_escape(const char *str_in, int size_in, + char *str_out, int quote) +{ + int i; + int size_out = 0; + char ch; + + for (i = 0; i < size_in; ++i) { + ch = str_in[i]; + if (quote ? (ch == '"' || ch == '\\') : (isspace(ch) || ch == ',' || ch == '=')) { + str_out[size_out++] = '\\'; + } + else if (ch == '\\') { + str_out[size_out++] = '\\'; + } + str_out[size_out++] = ch; + } + + return size_out; +} + +static int append_string(cfl_sds_t *buf, cfl_sds_t str) +{ + int len; + int size; + char *esc_buf; + + len = cfl_sds_len(str); + esc_buf = malloc(len * 2); + if (!esc_buf) { + cmt_errno(); + return -1; + } + + size = line_protocol_escape(str, len, esc_buf, 0); + cfl_sds_cat_safe(buf, esc_buf, size); + + free(esc_buf); + return 0; +} + +static void format_metric(struct cmt *cmt, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int i; + int n; + int count = 0; + int static_labels = 0; + struct cmt_map_label *label_k; + struct cmt_map_label *label_v; + struct cfl_list *head; + struct cmt_opts *opts; + struct cmt_label *slabel; + + if (map->type == CMT_SUMMARY && !metric->sum_quantiles_set) { + return; + } + + opts = map->opts; + + /* Measurement */ + cfl_sds_cat_safe(buf, opts->ns, cfl_sds_len(opts->ns)); + + if (cfl_sds_len(opts->subsystem) > 0) { + cfl_sds_cat_safe(buf, "_", 1); + cfl_sds_cat_safe(buf, opts->subsystem, cfl_sds_len(opts->subsystem)); + } + + /* Static labels (tags) */ + static_labels = cmt_labels_count(cmt->static_labels); + if (static_labels > 0) { + cfl_sds_cat_safe(buf, ",", 1); + cfl_list_foreach(head, &cmt->static_labels->list) { + count++; + slabel = cfl_list_entry(head, struct cmt_label, _head); + + /* key */ + append_string(buf, slabel->key); + + /* = */ + cfl_sds_cat_safe(buf, "=", 1); + + /* val */ + append_string(buf, slabel->val); + + if (count < static_labels) { + cfl_sds_cat_safe(buf, ",", 1); + } + } + } + + /* Labels / Tags */ + n = cfl_list_size(&metric->labels); + if (n > 0) { + cfl_sds_cat_safe(buf, ",", 1); + + label_k = cfl_list_entry_first(&map->label_keys, struct cmt_map_label, _head); + + i = 1; + cfl_list_foreach(head, &metric->labels) { + label_v = cfl_list_entry(head, struct cmt_map_label, _head); + + /* key */ + append_string(buf, label_k->name); + cfl_sds_cat_safe(buf, "=", 1); + append_string(buf, label_v->name); + + if (i < n) { + cfl_sds_cat_safe(buf, ",", 1); + } + i++; + + label_k = cfl_list_entry_next(&label_k->_head, struct cmt_map_label, + _head, &map->label_keys); + } + } + + cfl_sds_cat_safe(buf, " ", 1); + append_metric_value(map, buf, metric); +} + +static void format_metrics(struct cmt *cmt, + cfl_sds_t *buf, struct cmt_map *map) +{ + struct cfl_list *head; + struct cmt_metric *metric; + + /* Simple metric, no labels */ + if (map->metric_static_set == 1) { + format_metric(cmt, buf, map, &map->metric); + } + + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + format_metric(cmt, buf, map, metric); + } +} + +/* Format all the registered metrics in Prometheus Text format */ +cfl_sds_t cmt_encode_influx_create(struct cmt *cmt) +{ + cfl_sds_t buf; + struct cfl_list *head; + struct cmt_counter *counter; + struct cmt_gauge *gauge; + struct cmt_untyped *untyped; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + + /* Allocate a 1KB of buffer */ + buf = cfl_sds_create_size(1024); + if (!buf) { + return NULL; + } + + /* Counters */ + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + format_metrics(cmt, &buf, counter->map); + } + + /* Gauges */ + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + format_metrics(cmt, &buf, gauge->map); + } + + /* Summaries */ + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + format_metrics(cmt, &buf, summary->map); + } + + /* Histograms */ + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + format_metrics(cmt, &buf, histogram->map); + } + + /* Untyped */ + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + format_metrics(cmt, &buf, untyped->map); + } + + return buf; +} + +void cmt_encode_influx_destroy(cfl_sds_t text) +{ + cfl_sds_destroy(text); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_encode_msgpack.c b/fluent-bit/lib/cmetrics/src/cmt_encode_msgpack.c new file mode 100644 index 00000000..b31a78e3 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_encode_msgpack.c @@ -0,0 +1,552 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_compat.h> +#include <cmetrics/cmt_encode_msgpack.h> +#include <cmetrics/cmt_variant_utils.h> + +struct cmt_map_label *create_label(char *label_text) +{ + struct cmt_map_label *new_label; + + new_label = calloc(1, sizeof(struct cmt_map_label)); + + if (NULL != new_label) { + new_label->name = cfl_sds_create(label_text); + + if (NULL == new_label->name) { + free(new_label); + + new_label = NULL; + } + } + + return new_label; +} + +static void pack_header(mpack_writer_t *writer, struct cmt *cmt, struct cmt_map *map) +{ + struct cmt_opts *opts; + struct cfl_list *head; + struct cmt_map_label *label; + size_t index; + struct cmt_summary *summary = NULL; + struct cmt_histogram *histogram = NULL; + struct cmt_counter *counter = NULL; + size_t meta_field_count; + + opts = map->opts; + meta_field_count = 4; + + if (map->type == CMT_HISTOGRAM) { + histogram = (struct cmt_histogram *) map->parent; + + meta_field_count++; + } + else if (map->type == CMT_SUMMARY) { + summary = (struct cmt_summary *) map->parent; + + meta_field_count++; + } + else if (map->type == CMT_COUNTER){ + counter = (struct cmt_counter *) map->parent; + + meta_field_count++; + } + + /* 'meta' */ + mpack_write_cstr(writer, "meta"); + mpack_start_map(writer, meta_field_count); + + /* 'ver' */ + mpack_write_cstr(writer, "ver"); + mpack_write_uint(writer, MSGPACK_ENCODER_VERSION); + + /* 'type' */ + mpack_write_cstr(writer, "type"); + mpack_write_uint(writer, map->type); + + /* 'opts' */ + mpack_write_cstr(writer, "opts"); + mpack_start_map(writer, 4); + + /* opts['ns'] */ + mpack_write_cstr(writer, "ns"); + mpack_write_cstr(writer, opts->ns); + + /* opts['subsystem'] */ + mpack_write_cstr(writer, "ss"); + mpack_write_cstr(writer, opts->subsystem); + + /* opts['name'] */ + mpack_write_cstr(writer, "name"); + mpack_write_cstr(writer, opts->name); + + /* opts['description'] */ + mpack_write_cstr(writer, "desc"); + mpack_write_cstr(writer, opts->description); + + mpack_finish_map(writer); /* 'opts' */ + + /* 'labels' (label keys) */ + mpack_write_cstr(writer, "labels"); + mpack_start_array(writer, map->label_count); + cfl_list_foreach(head, &map->label_keys) { + label = cfl_list_entry(head, struct cmt_map_label, _head); + + mpack_write_cstr(writer, label->name); + } + mpack_finish_array(writer); + + if (map->type == CMT_HISTOGRAM) { + /* 'buckets' (histogram buckets) */ + mpack_write_cstr(writer, "buckets"); + + if (histogram->buckets != NULL) { + mpack_start_array(writer, histogram->buckets->count); + + for (index = 0 ; + index < histogram->buckets->count ; + index++) { + mpack_write_double(writer, histogram->buckets->upper_bounds[index]); + } + } + else { + mpack_start_array(writer, 0); + } + + mpack_finish_array(writer); + } + else if (map->type == CMT_SUMMARY) { + /* 'quantiles' (summary quantiles) */ + mpack_write_cstr(writer, "quantiles"); + + mpack_start_array(writer, summary->quantiles_count); + + for (index = 0 ; + index < summary->quantiles_count ; + index++) { + mpack_write_double(writer, summary->quantiles[index]); + } + + mpack_finish_array(writer); + } + else if (map->type == CMT_COUNTER){ + /* aggregation_type */ + mpack_write_cstr(writer, "aggregation_type"); + mpack_write_int(writer, counter->aggregation_type); + } + + mpack_finish_map(writer); /* 'meta' */ +} + +static int pack_metric(mpack_writer_t *writer, struct cmt_map *map, struct cmt_metric *metric) +{ + int c_labels; + int s; + double val; + size_t index; + struct cfl_list *head; + struct cmt_map_label *label; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + + c_labels = cfl_list_size(&metric->labels); + + s = 3; + + if (c_labels > 0) { + s++; + } + + mpack_start_map(writer, s); + + mpack_write_cstr(writer, "ts"); + mpack_write_uint(writer, metric->timestamp); + + if (map->type == CMT_HISTOGRAM) { + histogram = (struct cmt_histogram *) map->parent; + + mpack_write_cstr(writer, "histogram"); + mpack_start_map(writer, 3); + + mpack_write_cstr(writer, "buckets"); + mpack_start_array(writer, histogram->buckets->count + 1); + for (index = 0 ; + index <= histogram->buckets->count ; + index++) { + mpack_write_uint(writer, cmt_metric_hist_get_value(metric, index)); + } + + mpack_finish_array(writer); + + mpack_write_cstr(writer, "sum"); + mpack_write_double(writer, cmt_metric_hist_get_sum_value(metric)); + + mpack_write_cstr(writer, "count"); + mpack_write_uint(writer, cmt_metric_hist_get_count_value(metric)); + + mpack_finish_map(writer); /* 'histogram' */ + } + else if (map->type == CMT_SUMMARY) { + summary = (struct cmt_summary *) map->parent; + + mpack_write_cstr(writer, "summary"); + mpack_start_map(writer, 4); + + mpack_write_cstr(writer, "quantiles_set"); + mpack_write_uint(writer, metric->sum_quantiles_set); + + mpack_write_cstr(writer, "quantiles"); + mpack_start_array(writer, summary->quantiles_count); + + for (index = 0 ; index < summary->quantiles_count ; index++) { + mpack_write_uint(writer, metric->sum_quantiles[index]); + } + + mpack_finish_array(writer); + + mpack_write_cstr(writer, "count"); + mpack_write_uint(writer, cmt_summary_get_count_value(metric)); + + mpack_write_cstr(writer, "sum"); + mpack_write_uint(writer, metric->sum_sum); + + mpack_finish_map(writer); /* 'summary' */ + } + else { + mpack_write_cstr(writer, "value"); + val = cmt_metric_get_value(metric); + mpack_write_double(writer, val); + } + + s = cfl_list_size(&metric->labels); + if (s > 0) { + mpack_write_cstr(writer, "labels"); + mpack_start_array(writer, c_labels); + + cfl_list_foreach(head, &metric->labels) { + label = cfl_list_entry(head, struct cmt_map_label, _head); + + if (label->name != NULL) { + mpack_write_cstr(writer, label->name); + } + else { + mpack_write_nil(writer); + } + } + + mpack_finish_array(writer); + } + + mpack_write_cstr(writer, "hash"); + mpack_write_uint(writer, metric->hash); + + mpack_finish_map(writer); + + return 0; +} + +static int pack_basic_type(mpack_writer_t *writer, struct cmt *cmt, struct cmt_map *map) +{ + int values_size = 0; + struct cfl_list *head; + struct cmt_metric *metric; + + /* metric scope dictionary that holds meta and values*/ + mpack_start_map(writer, 2); + + pack_header(writer, cmt, map); + + if (map->metric_static_set) { + values_size++; + } + values_size += cfl_list_size(&map->metrics); + + mpack_write_cstr(writer, "values"); + mpack_start_array(writer, values_size); + + if (map->metric_static_set) { + pack_metric(writer, map, &map->metric); + } + + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + pack_metric(writer, map, metric); + } + mpack_finish_array(writer); + + mpack_finish_map(writer); + + return 0; +} + +static void pack_static_labels(mpack_writer_t *writer, struct cmt *cmt) +{ + struct cmt_label *static_label; + struct cfl_list *head; + + /* 'static_labels' (static labels) */ + mpack_write_cstr(writer, "static_labels"); + + mpack_start_array(writer, cfl_list_size(&cmt->static_labels->list)); + + cfl_list_foreach(head, &cmt->static_labels->list) { + static_label = cfl_list_entry(head, struct cmt_label, _head); + + mpack_start_array(writer, 2); + + mpack_write_cstr(writer, static_label->key); + mpack_write_cstr(writer, static_label->val); + + mpack_finish_array(writer); + } + + mpack_finish_array(writer); +} + +static int pack_static_processing_section(mpack_writer_t *writer, struct cmt *cmt) +{ + mpack_write_cstr(writer, "processing"); + + mpack_start_map(writer, 1); + + pack_static_labels(writer, cmt); + + mpack_finish_map(writer); /* 'processing' */ + + return 0; +} + +static int pack_context_header(mpack_writer_t *writer, struct cmt *cmt) +{ + int result; + + mpack_write_cstr(writer, "meta"); + mpack_start_map(writer, 3); + + mpack_write_cstr(writer, "cmetrics"); + result = pack_cfl_variant_kvlist(writer, cmt->internal_metadata); + + if (result != 0) { + return -1; + } + + mpack_write_cstr(writer, "external"); + result = pack_cfl_variant_kvlist(writer, cmt->external_metadata); + + if (result != 0) { + return -2; + } + + pack_static_processing_section(writer, cmt); + + mpack_finish_map(writer); /* 'context_header' */ + + return 0; +} + +static int pack_context_metrics(mpack_writer_t *writer, struct cmt *cmt) +{ + size_t metric_count; + struct cmt_histogram *histogram; + struct cmt_summary *summary; + struct cmt_untyped *untyped; + struct cmt_counter *counter; + struct cmt_gauge *gauge; + struct cfl_list *head; + + metric_count = 0; + metric_count += cfl_list_size(&cmt->counters); + metric_count += cfl_list_size(&cmt->gauges); + metric_count += cfl_list_size(&cmt->untypeds); + metric_count += cfl_list_size(&cmt->summaries); + metric_count += cfl_list_size(&cmt->histograms); + + mpack_write_cstr(writer, "metrics"); + mpack_start_array(writer, metric_count); + + /* Counters */ + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + pack_basic_type(writer, cmt, counter->map); + } + + /* Gauges */ + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + pack_basic_type(writer, cmt, gauge->map); + } + + /* Untyped */ + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + pack_basic_type(writer, cmt, untyped->map); + } + + /* Summary */ + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + pack_basic_type(writer, cmt, summary->map); + } + + /* Histogram */ + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + pack_basic_type(writer, cmt, histogram->map); + } + + mpack_finish_array(writer); + + return 0; +} + +static int pack_context(mpack_writer_t *writer, struct cmt *cmt) +{ + int result; + + mpack_start_map(writer, 2); + + result = pack_context_header(writer, cmt); + + if (result != 0) { + return -1; + } + + result = pack_context_metrics(writer, cmt); + + if (result != 0) { + return -2; + } + + mpack_finish_map(writer); /* outermost context scope */ + + return 0; +} + +/* Takes a cmetrics context and serialize it using msgpack */ +int cmt_encode_msgpack_create(struct cmt *cmt, char **out_buf, size_t *out_size) +{ + char *data; + size_t size; + mpack_writer_t writer; + int result; + + /* + * CMetrics data schema + + { + 'meta' => { + 'cmetrics' => { + 'producer': STRING + }, + 'external' => { ... }, + 'processing' => { + 'static_labels' => [ + [STRING, STRING], ... + ] + } + }, + 'metrics' => [ + { + 'meta' => { + 'ver' => INTEGER + 'type' => INTEGER + '0' = counter + '1' = gauge + '2' = histogram (WIP) + 'opts' => { + 'ns' => ns + 'subsystem' => subsystem + 'name' => name + 'description' => description + }, + 'label_keys' => [STRING, ...], + 'buckets' => [n, ...] + }, + 'values' => [ + { + 'ts' : nanosec timestamp, + 'value': float64 value, + 'label_values': [STRING, ...], + 'histogram':{ + 'sum': float64, + 'count': uint64, + 'buckets': [n, ...] + }, + 'summary': { + 'sum': float64, + 'count': uint64, + 'quantiles': [n, ...], + 'quantiles_set': uint64 + }, + 'hash': uint64 value + } + ] + }, ... + ] + } + * + * + * The following fields are metric type specific and are only + * included for histograms : + * meta->buckets + * values[n]->buckets + * values[n]->count + * values[n]->sum + */ + + if (cmt == NULL) { + return -1; + } + + mpack_writer_init_growable(&writer, &data, &size); + + result = pack_context(&writer, cmt); + + if (mpack_writer_destroy(&writer) != mpack_ok) { + fprintf(stderr, "An error occurred encoding the data!\n"); + + return -1; + } + + if (result != 0) { + return result; + } + + *out_buf = data; + *out_size = size; + + return 0; +} + +void cmt_encode_msgpack_destroy(char *out_buf) +{ + if (NULL != out_buf) { + MPACK_FREE(out_buf); + } +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_encode_opentelemetry.c b/fluent-bit/lib/cmetrics/src/cmt_encode_opentelemetry.c new file mode 100644 index 00000000..8c934186 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_encode_opentelemetry.c @@ -0,0 +1,2592 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_encode_opentelemetry.h> + +static Opentelemetry__Proto__Metrics__V1__ScopeMetrics ** + initialize_scope_metrics_list( + size_t element_count); + +static void destroy_scope_metric_list( + Opentelemetry__Proto__Metrics__V1__ScopeMetrics **metric_list); + +struct cfl_kvlist *fetch_metadata_kvlist_key( + struct cfl_kvlist *kvlist, char *key) +{ + struct cfl_variant *entry_variant; + struct cfl_kvlist *entry_kvlist; + + if (kvlist == NULL) { + return NULL; + } + + entry_variant = cfl_kvlist_fetch(kvlist, key); + + if (entry_variant != NULL) { + entry_kvlist = entry_variant->data.as_kvlist; + } + else { + entry_kvlist = NULL; + } + + return entry_kvlist; +} + + +static int is_string_releaseable(char *address); + +static int is_metric_empty(struct cmt_map *map); + +static size_t get_metric_count(struct cmt *cmt); + +static Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile * + initialize_summary_value_at_quantile( + double quantile, double value); + +static void destroy_summary_value_at_quantile( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile *value); + +static Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile ** + initialize_summary_value_at_quantile_list( + size_t element_count); + +static void destroy_summary_value_at_quantile_list( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile **list); + + +static void destroy_metrics_data( + Opentelemetry__Proto__Metrics__V1__MetricsData *metrics_data); + +static Opentelemetry__Proto__Metrics__V1__MetricsData * + initialize_metrics_data(size_t resource_metrics_count); + +static void destroy_resource( + Opentelemetry__Proto__Resource__V1__Resource *resource); + +static void destroy_resource_metrics( + Opentelemetry__Proto__Metrics__V1__ResourceMetrics *resource_metrics); + +static Opentelemetry__Proto__Metrics__V1__ResourceMetrics * + initialize_resource_metrics( + struct cfl_kvlist *resource_metrics_root, + Opentelemetry__Proto__Resource__V1__Resource *resource, + size_t instrumentation_library_metrics_element_count); + +static void destroy_resource_metrics_list( + Opentelemetry__Proto__Metrics__V1__ResourceMetrics **resource_metrics_list); + +static Opentelemetry__Proto__Metrics__V1__ResourceMetrics ** + initialize_resource_metrics_list( + size_t element_count); + +static Opentelemetry__Proto__Common__V1__InstrumentationScope * + initialize_instrumentation_scope( + struct cfl_kvlist *scope_root, + int *error_detection_flag); + +static void destroy_scope_metrics( + Opentelemetry__Proto__Metrics__V1__ScopeMetrics *metric); + +static Opentelemetry__Proto__Metrics__V1__ScopeMetrics * + initialize_scope_metrics( + struct cfl_kvlist *scope_metrics_root, + size_t metric_element_count); + +static int append_metric_to_scope_metrics( + Opentelemetry__Proto__Metrics__V1__ScopeMetrics *instrumentation_scope_metrics, + Opentelemetry__Proto__Metrics__V1__Metric *metric, + size_t metric_slot_hint); + +static void destroy_scope_metric_list( + Opentelemetry__Proto__Metrics__V1__ScopeMetrics **metric_list); + +static void destroy_attribute( + Opentelemetry__Proto__Common__V1__KeyValue *attribute); + +static Opentelemetry__Proto__Common__V1__KeyValue * + initialize_string_attribute(char *key, char *value); + +static void destroy_attribute_list( + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list); + +static Opentelemetry__Proto__Common__V1__KeyValue ** + initialize_attribute_list( + size_t element_count); + +static void destroy_numerical_data_point( + Opentelemetry__Proto__Metrics__V1__NumberDataPoint *data_point); + +static void destroy_summary_data_point( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *data_point); + +static void destroy_histogram_data_point( + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *data_point); + +static void destroy_data_point( + void *data_point, + int data_point_type); + +static void destroy_numerical_data_point_list( + Opentelemetry__Proto__Metrics__V1__NumberDataPoint **data_point_list); + +static void destroy_summary_data_point_list( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint **data_point_list); + +static void destroy_histogram_data_point_list( + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint **data_point_list); + +static Opentelemetry__Proto__Metrics__V1__NumberDataPoint * + initialize_numerical_data_point( + uint64_t start_time, + uint64_t timestamp, + double value, + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list, + size_t attribute_count); + +static Opentelemetry__Proto__Metrics__V1__SummaryDataPoint * + initialize_summary_data_point( + uint64_t start_time, + uint64_t timestamp, + uint64_t count, + double sum, + size_t quantile_count, + double *quantile_list, + size_t value_count, + uint64_t *value_list, + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list, + size_t attribute_count); + +static Opentelemetry__Proto__Metrics__V1__HistogramDataPoint * + initialize_histogram_data_point( + uint64_t start_time, + uint64_t timestamp, + uint64_t count, + double sum, + size_t bucket_count, + uint64_t *bucket_list, + size_t boundary_count, + double *boundary_list, + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list, + size_t attribute_count); + +static int append_attribute_to_numerical_data_point( + Opentelemetry__Proto__Metrics__V1__NumberDataPoint *data_point, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint); + +static int append_attribute_to_summary_data_point( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *data_point, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint); + +static int append_attribute_to_histogram_data_point( + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *data_point, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint); + +static int append_attribute_to_data_point( + void *data_point, + int data_point_type, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint); + +static int append_attribute_to_data_point( + void *data_point, + int data_point_type, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint); + +static Opentelemetry__Proto__Metrics__V1__NumberDataPoint ** + initialize_numerical_data_point_list( + size_t element_count); + +static Opentelemetry__Proto__Metrics__V1__HistogramDataPoint ** + initialize_histogram_data_point_list( + size_t element_count); + +static void destroy_metric( + Opentelemetry__Proto__Metrics__V1__Metric *metric); + +static Opentelemetry__Proto__Metrics__V1__Metric * + initialize_metric(int type, + char *name, + char *description, + char *unit, + int monotonism_flag, + int aggregation_temporality_type, + size_t data_point_count); + +static int append_data_point_to_metric( + Opentelemetry__Proto__Metrics__V1__Metric *metric, + void *data_point, + size_t data_point_slot_hint); + +static void destroy_metric_list( + Opentelemetry__Proto__Metrics__V1__Metric **metric_list); + +static Opentelemetry__Proto__Metrics__V1__Metric ** + initialize_metric_list( + size_t element_count); + +void cmt_encode_opentelemetry_destroy(cfl_sds_t text); + +static void destroy_opentelemetry_context( + struct cmt_opentelemetry_context *context); + +static struct cmt_opentelemetry_context *initialize_opentelemetry_context( + struct cmt *cmt); + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_to_otlp_any_value(struct cfl_variant *value); +static inline Opentelemetry__Proto__Common__V1__KeyValue *cfl_variant_kvpair_to_otlp_kvpair(struct cfl_kvpair *input_pair); +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_kvlist_to_otlp_any_value(struct cfl_variant *value); + +static inline void otlp_any_value_destroy(Opentelemetry__Proto__Common__V1__AnyValue *value); +static inline void otlp_kvpair_destroy(Opentelemetry__Proto__Common__V1__KeyValue *kvpair); +static inline void otlp_kvlist_destroy(Opentelemetry__Proto__Common__V1__KeyValueList *kvlist); +static inline void otlp_array_destroy(Opentelemetry__Proto__Common__V1__ArrayValue *array); + +static inline void otlp_kvpair_list_destroy(Opentelemetry__Proto__Common__V1__KeyValue **pair_list, size_t entry_count); + +static inline void otlp_kvpair_destroy(Opentelemetry__Proto__Common__V1__KeyValue *kvpair) +{ + if (kvpair != NULL) { + if (kvpair->key != NULL) { + free(kvpair->key); + } + + if (kvpair->value != NULL) { + otlp_any_value_destroy(kvpair->value); + } + + free(kvpair); + } +} + +static inline void otlp_kvlist_destroy(Opentelemetry__Proto__Common__V1__KeyValueList *kvlist) +{ + size_t index; + + if (kvlist != NULL) { + if (kvlist->values != NULL) { + for (index = 0 ; index < kvlist->n_values ; index++) { + otlp_kvpair_destroy(kvlist->values[index]); + } + + free(kvlist->values); + } + + free(kvlist); + } +} + +static inline void otlp_array_destroy(Opentelemetry__Proto__Common__V1__ArrayValue *array) +{ + size_t index; + + if (array != NULL) { + if (array->values != NULL) { + for (index = 0 ; index < array->n_values ; index++) { + otlp_any_value_destroy(array->values[index]); + } + + free(array->values); + } + + free(array); + } +} + +static inline void otlp_any_value_destroy(Opentelemetry__Proto__Common__V1__AnyValue *value) +{ + if (value != NULL) { + if (value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE) { + if (value->string_value != NULL) { + free(value->string_value); + } + } + else if (value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_ARRAY_VALUE) { + if (value->array_value != NULL) { + otlp_array_destroy(value->array_value); + } + } + else if (value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_KVLIST_VALUE) { + if (value->kvlist_value != NULL) { + otlp_kvlist_destroy(value->kvlist_value); + } + } + else if (value->value_case == OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BYTES_VALUE) { + if (value->bytes_value.data != NULL) { + free(value->bytes_value.data); + } + } + + free(value); + } +} + +static inline Opentelemetry__Proto__Common__V1__KeyValue **otlp_kvpair_list_initialize(size_t entry_count) +{ + Opentelemetry__Proto__Common__V1__KeyValue **result; + + result = \ + calloc(entry_count, sizeof(Opentelemetry__Proto__Common__V1__KeyValue *)); + + return result; +} + + +static Opentelemetry__Proto__Common__V1__ArrayValue *otlp_array_value_initialize(size_t entry_count) +{ + Opentelemetry__Proto__Common__V1__ArrayValue *value; + + value = calloc(1, sizeof(Opentelemetry__Proto__Common__V1__ArrayValue)); + + if (value != NULL) { + opentelemetry__proto__common__v1__array_value__init(value); + + if (entry_count > 0) { + value->values = \ + calloc(entry_count, + sizeof(Opentelemetry__Proto__Common__V1__AnyValue *)); + + if (value->values == NULL) { + free(value); + + value = NULL; + } + else { + value->n_values = entry_count; + } + } + } + + return value; +} + +static Opentelemetry__Proto__Common__V1__KeyValue *otlp_kvpair_value_initialize() +{ + Opentelemetry__Proto__Common__V1__KeyValue *value; + + value = calloc(1, sizeof(Opentelemetry__Proto__Common__V1__KeyValue)); + + if (value != NULL) { + opentelemetry__proto__common__v1__key_value__init(value); + } + + return value; +} + +static Opentelemetry__Proto__Common__V1__KeyValueList *otlp_kvlist_value_initialize(size_t entry_count) +{ + Opentelemetry__Proto__Common__V1__KeyValueList *value; + + value = calloc(1, sizeof(Opentelemetry__Proto__Common__V1__KeyValueList)); + + if (value != NULL) { + opentelemetry__proto__common__v1__key_value_list__init(value); + + if (entry_count > 0) { + value->values = \ + calloc(entry_count, + sizeof(Opentelemetry__Proto__Common__V1__KeyValue *)); + + if (value->values == NULL) { + free(value); + + value = NULL; + } + else { + value->n_values = entry_count; + } + } + } + + return value; +} + +static Opentelemetry__Proto__Common__V1__AnyValue *otlp_any_value_initialize(int data_type, size_t entry_count) +{ + Opentelemetry__Proto__Common__V1__AnyValue *value; + + value = calloc(1, sizeof(Opentelemetry__Proto__Common__V1__AnyValue)); + + if (value == NULL) { + return NULL; + } + + opentelemetry__proto__common__v1__any_value__init(value); + + if (data_type == CFL_VARIANT_STRING) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE; + } + else if (data_type == CFL_VARIANT_BOOL) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BOOL_VALUE; + } + else if (data_type == CFL_VARIANT_INT) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_INT_VALUE; + } + else if (data_type == CFL_VARIANT_DOUBLE) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_DOUBLE_VALUE; + } + else if (data_type == CFL_VARIANT_ARRAY) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_ARRAY_VALUE; + + value->array_value = otlp_array_value_initialize(entry_count); + + if (value->array_value == NULL) { + free(value); + + value = NULL; + } + } + else if (data_type == CFL_VARIANT_KVLIST) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_KVLIST_VALUE; + + value->kvlist_value = otlp_kvlist_value_initialize(entry_count); + + if (value->kvlist_value == NULL) { + free(value); + + value = NULL; + } + } + else if (data_type == CFL_VARIANT_BYTES) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BYTES_VALUE; + } + else if (data_type == CFL_VARIANT_REFERENCE) { + value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE; + } + else { + free(value); + + value = NULL; + } + + return value; +} + +static inline Opentelemetry__Proto__Common__V1__KeyValue *cfl_variant_kvpair_to_otlp_kvpair(struct cfl_kvpair *input_pair) +{ + Opentelemetry__Proto__Common__V1__KeyValue *pair; + + pair = otlp_kvpair_value_initialize(); + + if (pair != NULL) { + pair->key = strdup(input_pair->key); + + if (pair->key != NULL) { + pair->value = cfl_variant_to_otlp_any_value(input_pair->val); + + if (pair->value == NULL) { + free(pair->key); + + pair->key = NULL; + } + } + + if (pair->key == NULL) { + free(pair); + + pair = NULL; + } + } + + return pair; +} + +static inline void otlp_kvpair_list_destroy(Opentelemetry__Proto__Common__V1__KeyValue **pair_list, size_t entry_count) +{ + size_t index; + + if (pair_list != NULL) { + for (index = 0 ; index < entry_count ; index++) { + otlp_kvpair_destroy(pair_list[index]); + } + + free(pair_list); + } +} + +static inline Opentelemetry__Proto__Common__V1__KeyValue **cfl_kvlist_to_otlp_kvpair_list(struct cfl_kvlist *kvlist) +{ + size_t entry_count; + Opentelemetry__Proto__Common__V1__KeyValue *keyvalue; + struct cfl_list *iterator; + Opentelemetry__Proto__Common__V1__KeyValue **result; + struct cfl_kvpair *kvpair; + size_t index; + + entry_count = cfl_kvlist_count(kvlist); + + result = otlp_kvpair_list_initialize(entry_count + 1); + + if (result != NULL) { + index = 0; + + cfl_list_foreach(iterator, &kvlist->list) { + kvpair = cfl_list_entry(iterator, struct cfl_kvpair, _head); + + keyvalue = cfl_variant_kvpair_to_otlp_kvpair(kvpair); + + if (keyvalue == NULL) { + otlp_kvpair_list_destroy(result, entry_count); + + result = NULL; + + break; + } + + result[index++] = keyvalue; + } + } + + return result; +} + + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_kvlist_to_otlp_any_value(struct cfl_variant *value) +{ + size_t entry_count; + Opentelemetry__Proto__Common__V1__KeyValue *keyvalue; + struct cfl_list *iterator; + Opentelemetry__Proto__Common__V1__AnyValue *result; + struct cfl_kvpair *kvpair; + struct cfl_kvlist *kvlist; + size_t index; + + + kvlist = value->data.as_kvlist; + + entry_count = cfl_kvlist_count(kvlist); + + result = otlp_any_value_initialize(CFL_VARIANT_KVLIST, entry_count); + + if (result != NULL) { + index = 0; + + cfl_list_foreach(iterator, &kvlist->list) { + kvpair = cfl_list_entry(iterator, struct cfl_kvpair, _head); + + keyvalue = cfl_variant_kvpair_to_otlp_kvpair(kvpair); + + if (keyvalue == NULL) { + otlp_any_value_destroy(result); + + result = NULL; + + break; + } + + result->kvlist_value->values[index++] = keyvalue; + } + } + + return result; +} + + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_array_to_otlp_any_value(struct cfl_variant *value) +{ + size_t entry_count; + Opentelemetry__Proto__Common__V1__AnyValue *entry_value; + Opentelemetry__Proto__Common__V1__AnyValue *result; + struct cfl_array *array; + size_t index; + + array = value->data.as_array; + + entry_count = array->entry_count; + + result = otlp_any_value_initialize(CFL_VARIANT_ARRAY, entry_count); + + if (result != NULL) { + index = 0; + + for (index = 0 ; index < entry_count ; index++) { + entry_value = cfl_variant_to_otlp_any_value(cfl_array_fetch_by_index(array, index)); + + if (entry_value == NULL) { + otlp_any_value_destroy(result); + + result = NULL; + + break; + } + + result->array_value->values[index] = entry_value; + } + } + + return result; +} + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_string_to_otlp_any_value(struct cfl_variant *value) +{ + Opentelemetry__Proto__Common__V1__AnyValue *result; + + result = otlp_any_value_initialize(CFL_VARIANT_STRING, 0); + + if (result != NULL) { + result->string_value = strdup(value->data.as_string); + + if (result->string_value == NULL) { + otlp_any_value_destroy(result); + + result = NULL; + } + } + + return result; +} + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_boolean_to_otlp_any_value(struct cfl_variant *value) +{ + Opentelemetry__Proto__Common__V1__AnyValue *result; + + result = otlp_any_value_initialize(CFL_VARIANT_BOOL, 0); + + if (result != NULL) { + result->bool_value = value->data.as_bool; + } + + return result; +} + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_int64_to_otlp_any_value(struct cfl_variant *value) +{ + Opentelemetry__Proto__Common__V1__AnyValue *result; + + result = otlp_any_value_initialize(CFL_VARIANT_INT, 0); + + if (result != NULL) { + result->int_value = value->data.as_int64; + } + + return result; +} + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_double_to_otlp_any_value(struct cfl_variant *value) +{ + Opentelemetry__Proto__Common__V1__AnyValue *result; + + result = otlp_any_value_initialize(CFL_VARIANT_DOUBLE, 0); + + if (result != NULL) { + result->double_value = value->data.as_double; + } + + return result; +} + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_binary_to_otlp_any_value(struct cfl_variant *value) +{ + Opentelemetry__Proto__Common__V1__AnyValue *result; + + result = otlp_any_value_initialize(CFL_VARIANT_BYTES, 0); + + if (result != NULL) { + result->bytes_value.len = cfl_sds_len(value->data.as_bytes); + result->bytes_value.data = calloc(result->bytes_value.len, sizeof(char)); + + if (result->bytes_value.data == NULL) { + otlp_any_value_destroy(result); + + result = NULL; + } + + memcpy(result->bytes_value.data, value->data.as_bytes, result->bytes_value.len); + } + + return result; +} + +static inline Opentelemetry__Proto__Common__V1__AnyValue *cfl_variant_to_otlp_any_value(struct cfl_variant *value) +{ + Opentelemetry__Proto__Common__V1__AnyValue *result; + + if (value->type == CFL_VARIANT_STRING) { + result = cfl_variant_string_to_otlp_any_value(value); + } + else if (value->type == CFL_VARIANT_BOOL) { + result = cfl_variant_boolean_to_otlp_any_value(value); + } + else if (value->type == CFL_VARIANT_INT) { + result = cfl_variant_int64_to_otlp_any_value(value); + } + else if (value->type == CFL_VARIANT_DOUBLE) { + result = cfl_variant_double_to_otlp_any_value(value); + } + else if (value->type == CFL_VARIANT_ARRAY) { + result = cfl_variant_array_to_otlp_any_value(value); + } + else if (value->type == CFL_VARIANT_KVLIST) { + result = cfl_variant_kvlist_to_otlp_any_value(value); + } + else if (value->type == CFL_VARIANT_BYTES) { + result = cfl_variant_binary_to_otlp_any_value(value); + } + else if (value->type == CFL_VARIANT_REFERENCE) { + result = cfl_variant_string_to_otlp_any_value(value); + } + else { + result = NULL; + } + + return result; +} + +static char *fetch_metadata_string_key(struct cfl_kvlist *metadata, char *key_name, int *error_flag) +{ + struct cfl_variant *value; + + *error_flag = CMT_FALSE; + + value = cfl_kvlist_fetch(metadata, key_name); + + if (value == NULL) { + return NULL; + } + + if (value->type != CFL_VARIANT_STRING) { + *error_flag = CMT_TRUE; + + return NULL; + } + + return cfl_sds_create(value->data.as_string); +} + +static int64_t fetch_metadata_int64_key(struct cfl_kvlist *metadata, char *key_name, int *error_flag) +{ + struct cfl_variant *value; + + *error_flag = CMT_FALSE; + + value = cfl_kvlist_fetch(metadata, key_name); + + if (value == NULL) { + return 0; + } + + if (value->type != CFL_VARIANT_INT) { + *error_flag = CMT_TRUE; + + return 0; + } + + return value->data.as_int64; +} + +static int is_string_releaseable(char *address) + { + return (address != NULL && + address != protobuf_c_empty_string); +} + +static int is_metric_empty(struct cmt_map *map) +{ + size_t sample_count; + + sample_count = cfl_list_size(&map->metrics); + + if (map->metric_static_set) { + sample_count++; + } + + return (sample_count == 0); +} + +static size_t get_metric_count(struct cmt *cmt) +{ + size_t metric_count; + struct cmt_histogram *histogram; + struct cmt_summary *summary; + struct cmt_untyped *untyped; + struct cmt_counter *counter; + struct cmt_gauge *gauge; + struct cfl_list *head; + + metric_count = 0; + + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + + metric_count += !is_metric_empty(counter->map); + } + + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + + metric_count += !is_metric_empty(gauge->map); + } + + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + + metric_count += !is_metric_empty(untyped->map); + } + + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + + metric_count += !is_metric_empty(summary->map); + } + + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + + metric_count += !is_metric_empty(histogram->map); + } + + return metric_count; +} + +static void destroy_metrics_data( + Opentelemetry__Proto__Metrics__V1__MetricsData *metrics_data) +{ + if (metrics_data != NULL) { + destroy_resource_metrics_list(metrics_data->resource_metrics); + + free(metrics_data); + } +} + +static Opentelemetry__Proto__Metrics__V1__MetricsData * + initialize_metrics_data(size_t resource_metrics_count) +{ + Opentelemetry__Proto__Metrics__V1__MetricsData *metrics_data; + + metrics_data = calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__MetricsData)); + + if (metrics_data == NULL) { + return NULL; + } + + opentelemetry__proto__metrics__v1__metrics_data__init(metrics_data); + + metrics_data->resource_metrics = initialize_resource_metrics_list(resource_metrics_count); + + if (metrics_data->resource_metrics == NULL) { + destroy_metrics_data(metrics_data); + + return NULL; + } + + metrics_data->n_resource_metrics = resource_metrics_count; + + return metrics_data; +} + +static void destroy_resource( + Opentelemetry__Proto__Resource__V1__Resource *resource) +{ + if (resource != NULL) { + if (resource->attributes != NULL) { + otlp_kvpair_list_destroy(resource->attributes, resource->n_attributes); + } + + free(resource); + } +} + +static void destroy_resource_metrics( + Opentelemetry__Proto__Metrics__V1__ResourceMetrics *resource_metrics) +{ + if (resource_metrics != NULL) { + if (is_string_releaseable(resource_metrics->schema_url)) { + cfl_sds_destroy(resource_metrics->schema_url); + } + + if (resource_metrics->resource != NULL) { + destroy_resource(resource_metrics->resource); + } + + if (resource_metrics->scope_metrics != NULL) { + destroy_scope_metric_list(resource_metrics->scope_metrics); + } + + free(resource_metrics); + } +} + +static Opentelemetry__Proto__Metrics__V1__ResourceMetrics * + initialize_resource_metrics( + struct cfl_kvlist *resource_metrics_root, + Opentelemetry__Proto__Resource__V1__Resource *resource, + size_t scope_metrics_element_count) +{ + int error_detection_flag; + Opentelemetry__Proto__Metrics__V1__ResourceMetrics *resource_metrics; + struct cfl_kvlist *metadata; + + metadata = fetch_metadata_kvlist_key(resource_metrics_root, "metadata"); + + resource_metrics = \ + calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__ResourceMetrics)); + + if (resource_metrics == NULL) { + return NULL; + } + + opentelemetry__proto__metrics__v1__resource_metrics__init( + resource_metrics); + + if (metadata != NULL) { + resource_metrics->schema_url = fetch_metadata_string_key(metadata, "schema_url", &error_detection_flag); + } + else { + error_detection_flag = CMT_FALSE; + } + + if (error_detection_flag) { + destroy_resource_metrics(resource_metrics); + + return NULL; + } + + resource_metrics->scope_metrics = \ + initialize_scope_metrics_list( + scope_metrics_element_count); + + if (resource_metrics->scope_metrics == NULL) { + destroy_resource_metrics(resource_metrics); + + return NULL; + } + + resource_metrics->n_scope_metrics = \ + scope_metrics_element_count; + + resource_metrics->resource = resource; + + return resource_metrics; +} + +static void destroy_resource_metrics_list( + Opentelemetry__Proto__Metrics__V1__ResourceMetrics **metric_list) +{ + size_t element_index; + + if (metric_list != NULL) { + for (element_index = 0 ; + metric_list[element_index] != NULL ; + element_index++) { + destroy_resource_metrics(metric_list[element_index]); + + metric_list[element_index] = NULL; + } + + free(metric_list); + } +} + +static Opentelemetry__Proto__Metrics__V1__ResourceMetrics ** + initialize_resource_metrics_list( + size_t element_count) +{ + Opentelemetry__Proto__Metrics__V1__ResourceMetrics **metric_list; + + metric_list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Metrics__V1__ResourceMetrics *)); + + return metric_list; +} + +static void destroy_scope_metrics( + Opentelemetry__Proto__Metrics__V1__ScopeMetrics *metric) +{ + if (metric != NULL) { + destroy_metric_list(metric->metrics); + + free(metric); + } +} + +void destroy_instrumentation_scope(Opentelemetry__Proto__Common__V1__InstrumentationScope *scope) +{ + if (scope->name != NULL) { + cfl_sds_destroy(scope->name); + } + + if (scope->version != NULL) { + cfl_sds_destroy(scope->version); + } + + if (scope->attributes != NULL) { + destroy_attribute_list(scope->attributes); + } + + free(scope); +} + +static Opentelemetry__Proto__Common__V1__InstrumentationScope * + initialize_instrumentation_scope( + struct cfl_kvlist *scope_root, + int *error_detection_flag) +{ + struct cfl_kvlist *attributes; + struct cfl_kvlist *metadata; + Opentelemetry__Proto__Common__V1__InstrumentationScope *scope; + + *error_detection_flag = CMT_FALSE; + + if (scope_root == NULL) { + return NULL; + } + + attributes = fetch_metadata_kvlist_key(scope_root, "attributes"); + metadata = fetch_metadata_kvlist_key(scope_root, "metadata"); + + if (cfl_kvlist_count(attributes) == 0 && + cfl_kvlist_count(metadata) == 0) { + return NULL; + } + + scope = \ + calloc(1, sizeof(Opentelemetry__Proto__Common__V1__InstrumentationScope)); + + if (scope == NULL) { + *error_detection_flag = CMT_TRUE; + + return NULL; + } + + opentelemetry__proto__common__v1__instrumentation_scope__init(scope); + + scope->attributes = cfl_kvlist_to_otlp_kvpair_list(attributes); + + if (scope->attributes == NULL) { + *error_detection_flag = CMT_TRUE; + } + + scope->n_attributes = cfl_kvlist_count(attributes); + + if (!(*error_detection_flag)) { + scope->dropped_attributes_count = (uint32_t) fetch_metadata_int64_key( + metadata, + "dropped_attributes_count", + error_detection_flag); + } + + if (!(*error_detection_flag)) { + scope->name = fetch_metadata_string_key(metadata, "name", error_detection_flag); + } + + if (!(*error_detection_flag)) { + scope->version = fetch_metadata_string_key(metadata, "version", error_detection_flag); + } + + if (*error_detection_flag && + scope != NULL) { + destroy_instrumentation_scope(scope); + + scope = NULL; + } + + return scope; +} + +static Opentelemetry__Proto__Metrics__V1__ScopeMetrics * + initialize_scope_metrics( + struct cfl_kvlist *scope_metrics_root, + size_t metric_element_count) +{ + int error_detection_flag; + Opentelemetry__Proto__Metrics__V1__ScopeMetrics *scope_metrics; + struct cfl_kvlist *metadata; + + metadata = fetch_metadata_kvlist_key(scope_metrics_root, "metadata"); + + scope_metrics = \ + calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__ScopeMetrics)); + + if (scope_metrics == NULL) { + return NULL; + } + + opentelemetry__proto__metrics__v1__scope_metrics__init(scope_metrics); + + error_detection_flag = CMT_FALSE; + + if (metric_element_count > 0) { + scope_metrics->metrics = \ + initialize_metric_list(metric_element_count); + + if (scope_metrics->metrics == NULL) { + error_detection_flag = CMT_TRUE; + } + else { + scope_metrics->n_metrics = metric_element_count; + } + } + + if (!error_detection_flag && metadata != NULL) { + scope_metrics->schema_url = fetch_metadata_string_key(metadata, "schema_url", &error_detection_flag); + } + + if (error_detection_flag && + scope_metrics != NULL) { + destroy_scope_metrics(scope_metrics); + + scope_metrics = NULL; + } + + return scope_metrics; +} + +static int append_metric_to_scope_metrics( + Opentelemetry__Proto__Metrics__V1__ScopeMetrics *metrics, + Opentelemetry__Proto__Metrics__V1__Metric *metric, + size_t metric_slot_hint) +{ + size_t metric_slot_index; + + for (metric_slot_index = metric_slot_hint ; + metric_slot_index < metrics->n_metrics; + metric_slot_index++) { + if (metrics->metrics[metric_slot_index] == NULL) { + metrics->metrics[metric_slot_index] = metric; + + return CMT_ENCODE_OPENTELEMETRY_SUCCESS; + } + } + + return CMT_ENCODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; +} + +static void destroy_scope_metric_list( + Opentelemetry__Proto__Metrics__V1__ScopeMetrics **metric_list) +{ + size_t element_index; + + if (metric_list != NULL) { + for (element_index = 0 ; + metric_list[element_index] != NULL ; + element_index++) { + destroy_scope_metrics(metric_list[element_index]); + + metric_list[element_index] = NULL; + } + + free(metric_list); + } +} + +static Opentelemetry__Proto__Metrics__V1__ScopeMetrics ** + initialize_scope_metrics_list( + size_t element_count) +{ + Opentelemetry__Proto__Metrics__V1__ScopeMetrics **metric_list; + + metric_list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Metrics__V1__ScopeMetrics *)); + + return metric_list; +} + +static void destroy_attribute( + Opentelemetry__Proto__Common__V1__KeyValue *attribute) +{ + if (attribute != NULL) { + if (attribute->value != NULL) { + if (attribute->value->value_case == \ + OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE) { + if (is_string_releaseable(attribute->value->string_value)) { + cfl_sds_destroy(attribute->value->string_value); + } + } + + free(attribute->value); + } + + if (is_string_releaseable(attribute->key)) { + cfl_sds_destroy(attribute->key); + } + + free(attribute); + } +} + +static Opentelemetry__Proto__Common__V1__KeyValue * + initialize_string_attribute(char *key, char *value) +{ + Opentelemetry__Proto__Common__V1__KeyValue *attribute; + + attribute = calloc(1, + sizeof(Opentelemetry__Proto__Common__V1__KeyValue)); + + if (attribute == NULL) { + return NULL; + } + + opentelemetry__proto__common__v1__key_value__init(attribute); + + attribute->value = calloc(1, + sizeof(Opentelemetry__Proto__Common__V1__AnyValue)); + + if (attribute->value == NULL) { + destroy_attribute(attribute); + + return NULL; + } + + opentelemetry__proto__common__v1__any_value__init(attribute->value); + + attribute->value->string_value = cfl_sds_create(value); + + if (attribute->value->string_value == NULL) { + destroy_attribute(attribute); + + return NULL; + } + + attribute->value->value_case = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE; + + attribute->key = cfl_sds_create(key); + + if (attribute->key == NULL) { + destroy_attribute(attribute); + + return NULL; + } + + return attribute; +} + +static void destroy_attribute_list( + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list) +{ + size_t element_index; + + if (attribute_list != NULL) { + for (element_index = 0 ; + attribute_list[element_index] != NULL ; + element_index++) { + destroy_attribute(attribute_list[element_index]); + + attribute_list[element_index] = NULL; + } + + free(attribute_list); + } +} + +static Opentelemetry__Proto__Common__V1__KeyValue ** + initialize_attribute_list( + size_t element_count) +{ + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list; + + attribute_list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Common__V1__KeyValue *)); + + return attribute_list; +} + +static void destroy_numerical_data_point( + Opentelemetry__Proto__Metrics__V1__NumberDataPoint *data_point) +{ + if (data_point != NULL) { + destroy_attribute_list(data_point->attributes); + + free(data_point); + } +} + +static void destroy_summary_data_point( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *data_point) +{ + if (data_point != NULL) { + destroy_attribute_list(data_point->attributes); + + if (data_point->quantile_values != NULL) { + destroy_summary_value_at_quantile_list(data_point->quantile_values); + } + + free(data_point); + } +} + +static void destroy_histogram_data_point( + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *data_point) +{ + if (data_point != NULL) { + destroy_attribute_list(data_point->attributes); + + if (data_point->bucket_counts != NULL) { + free(data_point->bucket_counts); + } + + if (data_point->explicit_bounds != NULL) { + free(data_point->explicit_bounds); + } + + free(data_point); + } +} + +static void destroy_data_point( + void *data_point, + int data_point_type) +{ + switch (data_point_type) { + case CMT_COUNTER: + case CMT_GAUGE: + case CMT_UNTYPED: + return destroy_numerical_data_point(data_point); + case CMT_SUMMARY: + return destroy_summary_data_point(data_point); + case CMT_HISTOGRAM: + return destroy_histogram_data_point(data_point); + } +} + +static void destroy_numerical_data_point_list( + Opentelemetry__Proto__Metrics__V1__NumberDataPoint **data_point_list) +{ + size_t element_index; + + if (data_point_list != NULL) { + for (element_index = 0 ; + data_point_list[element_index] != NULL ; + element_index++) { + destroy_numerical_data_point(data_point_list[element_index]); + + data_point_list[element_index] = NULL; + } + + free(data_point_list); + } +} + +static void destroy_summary_data_point_list( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint **data_point_list) +{ + size_t element_index; + + if (data_point_list != NULL) { + for (element_index = 0 ; + data_point_list[element_index] != NULL ; + element_index++) { + destroy_summary_data_point(data_point_list[element_index]); + + data_point_list[element_index] = NULL; + } + + free(data_point_list); + } +} + +static void destroy_histogram_data_point_list( + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint **data_point_list) +{ + size_t element_index; + + if (data_point_list != NULL) { + for (element_index = 0 ; + data_point_list[element_index] != NULL ; + element_index++) { + destroy_histogram_data_point(data_point_list[element_index]); + + data_point_list[element_index] = NULL; + } + + free(data_point_list); + } +} + +static Opentelemetry__Proto__Metrics__V1__NumberDataPoint * + initialize_numerical_data_point( + uint64_t start_time, + uint64_t timestamp, + double value, + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list, + size_t attribute_count) +{ + Opentelemetry__Proto__Metrics__V1__NumberDataPoint *data_point; + + data_point = calloc(1, + sizeof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint)); + + if (data_point == NULL) { + return NULL; + } + + opentelemetry__proto__metrics__v1__number_data_point__init(data_point); + + data_point->start_time_unix_nano = start_time; + data_point->time_unix_nano = timestamp; + data_point->value_case = OPENTELEMETRY__PROTO__METRICS__V1__NUMBER_DATA_POINT__VALUE_AS_DOUBLE; + data_point->as_double = value; + data_point->attributes = attribute_list; + data_point->n_attributes = attribute_count; + + return data_point; +} + +static Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile * + initialize_summary_value_at_quantile( + double quantile, double value) +{ + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile *instance; + + instance = calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile)); + + if (instance != NULL) { + opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__init(instance); + + instance->quantile = quantile; + instance->value = value; + } + + return instance; +} + +static void destroy_summary_value_at_quantile( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile *value) +{ + if (value != NULL) { + free(value); + } +} + +static Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile ** + initialize_summary_value_at_quantile_list( + size_t element_count) +{ + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile **list; + + list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile *)); + + return list; +} + +static void destroy_summary_value_at_quantile_list( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile **list) +{ + size_t index; + + if (list != NULL) { + for (index = 0 ; + list[index] != NULL ; + index++) { + destroy_summary_value_at_quantile(list[index]); + + list[index] = NULL; + } + + free(list); + } +} + + + +static Opentelemetry__Proto__Metrics__V1__SummaryDataPoint * + initialize_summary_data_point( + uint64_t start_time, + uint64_t timestamp, + uint64_t count, + double sum, + size_t quantile_count, + double *quantile_list, + size_t value_count, + uint64_t *value_list, + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list, + size_t attribute_count) +{ + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *data_point; + size_t index; + + data_point = calloc(1, + sizeof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint)); + + if (data_point == NULL) { + return NULL; + } + + opentelemetry__proto__metrics__v1__summary_data_point__init(data_point); + + data_point->start_time_unix_nano = start_time; + data_point->time_unix_nano = timestamp; + + data_point->count = count; + data_point->sum = sum; + data_point->n_quantile_values = quantile_count; + + data_point->quantile_values = initialize_summary_value_at_quantile_list(quantile_count); + + if (data_point->quantile_values == NULL) { + cmt_errno(); + + free(data_point); + + return NULL; + } + + if (quantile_count > 0) { + if (value_list != NULL) { + for (index = 0 ; index < quantile_count ; index++) { + data_point->quantile_values[index] = + initialize_summary_value_at_quantile(quantile_list[index], + cmt_math_uint64_to_d64(value_list[index])); + + if (data_point->quantile_values[index] == NULL) { + destroy_summary_value_at_quantile_list(data_point->quantile_values); + + free(data_point); + + return NULL; + } + } + } + } + + data_point->attributes = attribute_list; + data_point->n_attributes = attribute_count; + + return data_point; +} + +static Opentelemetry__Proto__Metrics__V1__HistogramDataPoint * + initialize_histogram_data_point( + uint64_t start_time, + uint64_t timestamp, + uint64_t count, + double sum, + size_t bucket_count, + uint64_t *bucket_list, + size_t boundary_count, + double *boundary_list, + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list, + size_t attribute_count) +{ + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *data_point; + size_t index; + + data_point = calloc(1, + sizeof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint)); + + if (data_point == NULL) { + return NULL; + } + + opentelemetry__proto__metrics__v1__histogram_data_point__init(data_point); + + data_point->start_time_unix_nano = start_time; + data_point->time_unix_nano = timestamp; + + data_point->count = count; + data_point->n_bucket_counts = bucket_count; + + data_point->sum = sum; + + if (bucket_count > 0) { + data_point->bucket_counts = calloc(bucket_count, sizeof(uint64_t)); + + if (data_point->bucket_counts == NULL) { + cmt_errno(); + + free(data_point); + + return NULL; + } + + if (bucket_list != NULL) { + for (index = 0 ; index < bucket_count ; index++) { + data_point->bucket_counts[index] = bucket_list[index]; + } + } + } + + data_point->n_explicit_bounds = boundary_count; + + if (boundary_count > 0) { + data_point->explicit_bounds = calloc(boundary_count, sizeof(uint64_t)); + + if (data_point->explicit_bounds == NULL) { + cmt_errno(); + + if (data_point->bucket_counts != NULL) { + free(data_point->bucket_counts); + } + + free(data_point); + + return NULL; + } + + if (boundary_list != NULL) { + for (index = 0 ; index < boundary_count ; index++) { + data_point->explicit_bounds[index] = boundary_list[index]; + } + } + } + + data_point->attributes = attribute_list; + data_point->n_attributes = attribute_count; + + return data_point; +} + +static int append_attribute_to_numerical_data_point( + Opentelemetry__Proto__Metrics__V1__NumberDataPoint *data_point, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint) +{ + size_t attribute_slot_index; + + for (attribute_slot_index = attribute_slot_hint ; + attribute_slot_index < data_point->n_attributes; + attribute_slot_index++) { + if (data_point->attributes[attribute_slot_index] == NULL) { + data_point->attributes[attribute_slot_index] = attribute; + + return CMT_ENCODE_OPENTELEMETRY_SUCCESS; + } + } + + return CMT_ENCODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; +} + +static int append_attribute_to_summary_data_point( + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *data_point, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint) +{ + size_t attribute_slot_index; + + for (attribute_slot_index = attribute_slot_hint ; + attribute_slot_index < data_point->n_attributes; + attribute_slot_index++) { + if (data_point->attributes[attribute_slot_index] == NULL) { + data_point->attributes[attribute_slot_index] = attribute; + + return CMT_ENCODE_OPENTELEMETRY_SUCCESS; + } + } + + return CMT_ENCODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; +} + +static int append_attribute_to_histogram_data_point( + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *data_point, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint) +{ + size_t attribute_slot_index; + + for (attribute_slot_index = attribute_slot_hint ; + attribute_slot_index < data_point->n_attributes; + attribute_slot_index++) { + if (data_point->attributes[attribute_slot_index] == NULL) { + data_point->attributes[attribute_slot_index] = attribute; + + return CMT_ENCODE_OPENTELEMETRY_SUCCESS; + } + } + + return CMT_ENCODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; +} + +static int append_attribute_to_data_point( + void *data_point, + int data_point_type, + Opentelemetry__Proto__Common__V1__KeyValue *attribute, + size_t attribute_slot_hint) +{ + switch (data_point_type) { + case CMT_COUNTER: + case CMT_GAUGE: + case CMT_UNTYPED: + return append_attribute_to_numerical_data_point(data_point, + attribute, + attribute_slot_hint); + case CMT_SUMMARY: + return append_attribute_to_summary_data_point(data_point, + attribute, + attribute_slot_hint); + case CMT_HISTOGRAM: + return append_attribute_to_histogram_data_point(data_point, + attribute, + attribute_slot_hint); + } + + return CMT_ENCODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; +} + +static Opentelemetry__Proto__Metrics__V1__NumberDataPoint ** + initialize_numerical_data_point_list( + size_t element_count) +{ + Opentelemetry__Proto__Metrics__V1__NumberDataPoint **data_point_list; + + data_point_list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint *)); + + return data_point_list; +} + +static Opentelemetry__Proto__Metrics__V1__SummaryDataPoint ** + initialize_summary_data_point_list( + size_t element_count) +{ + Opentelemetry__Proto__Metrics__V1__SummaryDataPoint **data_point_list; + + data_point_list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *)); + + return data_point_list; +} + +static Opentelemetry__Proto__Metrics__V1__HistogramDataPoint ** + initialize_histogram_data_point_list( + size_t element_count) +{ + Opentelemetry__Proto__Metrics__V1__HistogramDataPoint **data_point_list; + + data_point_list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *)); + + if (data_point_list == NULL) { + return NULL; + } + + return data_point_list; +} + +static void destroy_metric( + Opentelemetry__Proto__Metrics__V1__Metric *metric) +{ + if (metric != NULL) { + if (is_string_releaseable(metric->name)) { + cfl_sds_destroy(metric->name); + metric->name = NULL; + } + + if (is_string_releaseable(metric->description)) { + cfl_sds_destroy(metric->description); + metric->description = NULL; + } + + if (is_string_releaseable(metric->unit)) { + cfl_sds_destroy(metric->unit); + metric->unit = NULL; + } + + if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUM) { + destroy_numerical_data_point_list(metric->sum->data_points); + + free(metric->sum); + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_GAUGE) { + destroy_numerical_data_point_list(metric->gauge->data_points); + + free(metric->gauge); + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUMMARY) { + destroy_summary_data_point_list(metric->summary->data_points); + + free(metric->histogram); + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_HISTOGRAM) { + destroy_histogram_data_point_list(metric->histogram->data_points); + + free(metric->histogram); + } + + free(metric); + } +} + +static Opentelemetry__Proto__Metrics__V1__Metric * + initialize_metric(int type, + char *name, + char *description, + char *unit, + int monotonism_flag, + int aggregation_temporality_type, + size_t data_point_count) +{ + Opentelemetry__Proto__Metrics__V1__Metric *metric; + + metric = calloc(1, + sizeof(Opentelemetry__Proto__Metrics__V1__Metric)); + + if (metric == NULL) { + return NULL; + } + + opentelemetry__proto__metrics__v1__metric__init(metric); + + metric->name = cfl_sds_create(name); + + if (metric->name == NULL) { + destroy_metric(metric); + + return NULL; + } + + if (description != NULL) { + metric->description = cfl_sds_create(description); + + if (metric->description == NULL) { + destroy_metric(metric); + + return NULL; + } + } + + if (unit != NULL) { + metric->unit = cfl_sds_create(unit); + + if (metric->unit == NULL) { + destroy_metric(metric); + + return NULL; + } + } + + if (type == CMT_COUNTER) { + metric->sum = calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__Sum)); + + if (metric->sum == NULL) { + destroy_metric(metric); + + return NULL; + } + + opentelemetry__proto__metrics__v1__sum__init(metric->sum); + + metric->data_case = OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUM; + metric->sum->data_points = initialize_numerical_data_point_list(data_point_count); + + if (metric->sum->data_points == NULL) { + destroy_metric(metric); + + return NULL; + } + + + metric->sum->aggregation_temporality = aggregation_temporality_type; + metric->sum->is_monotonic = monotonism_flag; + metric->sum->n_data_points = data_point_count; + } + else if (type == CMT_UNTYPED) { + metric->gauge = calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__Gauge)); + + if (metric->gauge == NULL) { + destroy_metric(metric); + + return NULL; + } + + opentelemetry__proto__metrics__v1__gauge__init(metric->gauge); + + metric->data_case = OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_GAUGE; + metric->gauge->data_points = initialize_numerical_data_point_list(data_point_count); + + if (metric->gauge->data_points == NULL) { + destroy_metric(metric); + + return NULL; + } + + metric->gauge->n_data_points = data_point_count; + } + else if (type == CMT_GAUGE) { + metric->gauge = calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__Gauge)); + + if (metric->gauge == NULL) { + destroy_metric(metric); + + return NULL; + } + + opentelemetry__proto__metrics__v1__gauge__init(metric->gauge); + + metric->data_case = OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_GAUGE; + metric->gauge->data_points = initialize_numerical_data_point_list(data_point_count); + + if (metric->gauge->data_points == NULL) { + destroy_metric(metric); + + return NULL; + } + + metric->gauge->n_data_points = data_point_count; + } + else if (type == CMT_SUMMARY) { + metric->summary = calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__Summary)); + + if (metric->summary == NULL) { + destroy_metric(metric); + + return NULL; + } + + opentelemetry__proto__metrics__v1__summary__init(metric->summary); + + metric->data_case = OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUMMARY; + metric->summary->data_points = initialize_summary_data_point_list(data_point_count); + + if (metric->summary->data_points == NULL) { + destroy_metric(metric); + + return NULL; + } + + metric->summary->n_data_points = data_point_count; + } + else if (type == CMT_HISTOGRAM) { + metric->histogram = calloc(1, sizeof(Opentelemetry__Proto__Metrics__V1__Histogram)); + + if (metric->histogram == NULL) { + destroy_metric(metric); + + return NULL; + } + + opentelemetry__proto__metrics__v1__histogram__init(metric->histogram); + + metric->data_case = OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_HISTOGRAM; + metric->histogram->data_points = initialize_histogram_data_point_list(data_point_count); + + if (metric->histogram->data_points == NULL) { + destroy_metric(metric); + + return NULL; + } + + metric->histogram->n_data_points = data_point_count; + metric->histogram->aggregation_temporality = aggregation_temporality_type; + } + + return metric; +} + +static int append_data_point_to_metric( + Opentelemetry__Proto__Metrics__V1__Metric *metric, + void *data_point, + size_t data_point_slot_hint) +{ + void **data_point_list; + size_t data_point_slot_index; + size_t data_point_slot_count; + + data_point_list = NULL; + data_point_slot_count = 0; + + if (metric != NULL) { + if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUM) { + data_point_list = (void **) metric->sum->data_points; + data_point_slot_count = metric->sum->n_data_points; + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_GAUGE) { + data_point_list = (void **) metric->gauge->data_points; + data_point_slot_count = metric->gauge->n_data_points; + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_SUMMARY) { + data_point_list = (void **) metric->summary->data_points; + data_point_slot_count = metric->summary->n_data_points; + } + else if (metric->data_case == OPENTELEMETRY__PROTO__METRICS__V1__METRIC__DATA_HISTOGRAM) { + data_point_list = (void **) metric->histogram->data_points; + data_point_slot_count = metric->histogram->n_data_points; + } + } + + for (data_point_slot_index = data_point_slot_hint ; + data_point_slot_index < data_point_slot_count; + data_point_slot_index++) { + if (data_point_list[data_point_slot_index] == NULL) { + data_point_list[data_point_slot_index] = data_point; + + return CMT_ENCODE_OPENTELEMETRY_SUCCESS; + } + } + + return CMT_ENCODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR; +} + +static void destroy_metric_list( + Opentelemetry__Proto__Metrics__V1__Metric **metric_list) +{ + size_t element_index; + + if (metric_list != NULL) { + for (element_index = 0 ; + metric_list[element_index] != NULL ; + element_index++) { + destroy_metric(metric_list[element_index]); + + metric_list[element_index] = NULL; + } + + free(metric_list); + } +} + +static Opentelemetry__Proto__Metrics__V1__Metric ** + initialize_metric_list( + size_t element_count) +{ + Opentelemetry__Proto__Metrics__V1__Metric **metric_list; + + metric_list = calloc(element_count + 1, + sizeof(Opentelemetry__Proto__Metrics__V1__Metric *)); + + if (metric_list == NULL) { + return NULL; + } + + return metric_list; +} + +static void destroy_opentelemetry_context( + struct cmt_opentelemetry_context *context) +{ + if (context != NULL) { + if (context->metrics_data != NULL) { + destroy_metrics_data(context->metrics_data); + } + + free(context); + } +} + +static Opentelemetry__Proto__Resource__V1__Resource * + initialize_resource( + struct cfl_kvlist *resource_root, + int *error_detection_flag) +{ + struct cfl_kvlist *attributes; + struct cfl_kvlist *metadata; + Opentelemetry__Proto__Resource__V1__Resource *resource; + + *error_detection_flag = CMT_FALSE; + + if (resource_root == NULL) { + return NULL; + } + + attributes = fetch_metadata_kvlist_key(resource_root, "attributes"); + metadata = fetch_metadata_kvlist_key(resource_root, "metadata"); + + if (cfl_kvlist_count(attributes) == 0 && + cfl_kvlist_count(metadata) == 0) { + return NULL; + } + + resource = \ + calloc(1, sizeof(Opentelemetry__Proto__Resource__V1__Resource)); + + if (resource == NULL) { + *error_detection_flag = CMT_TRUE; + + return NULL; + } + + opentelemetry__proto__resource__v1__resource__init(resource); + + resource->attributes = cfl_kvlist_to_otlp_kvpair_list(attributes); + + if (resource->attributes == NULL) { + *error_detection_flag = CMT_TRUE; + } + + resource->n_attributes = cfl_kvlist_count(attributes); + + if (!(*error_detection_flag)) { + resource->dropped_attributes_count = (uint32_t) fetch_metadata_int64_key( + metadata, + "dropped_attributes_count", + error_detection_flag); + } + + if (*error_detection_flag && + resource != NULL) { + destroy_resource(resource); + + resource = NULL; + } + + return resource; +} + +static struct cmt_opentelemetry_context *initialize_opentelemetry_context( + struct cmt *cmt) +{ + struct cfl_kvlist *resource_metrics_root; + struct cfl_kvlist *scope_metrics_root; + struct cfl_kvlist *resource_root; + struct cfl_kvlist *scope_root; + Opentelemetry__Proto__Resource__V1__Resource *resource; + struct cmt_opentelemetry_context *context; + int result; + + resource_metrics_root = fetch_metadata_kvlist_key(cmt->external_metadata, "resource_metrics"); + resource_root = fetch_metadata_kvlist_key(cmt->external_metadata, "resource"); + scope_metrics_root = fetch_metadata_kvlist_key(cmt->external_metadata, "scope_metrics"); + scope_root = fetch_metadata_kvlist_key(cmt->external_metadata, "scope"); + + result = CMT_ENCODE_OPENTELEMETRY_SUCCESS; + + context = calloc(1, sizeof(struct cmt_opentelemetry_context)); + + if (context == NULL) { + result = CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + + goto cleanup; + } + + memset(context, 0, sizeof(struct cmt_opentelemetry_context)); + + context->cmt = cmt; + + resource = initialize_resource(resource_root, &result); + + if (resource == NULL) { + if (result) { + result = CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + + goto cleanup; + } + } + + context->metrics_data = initialize_metrics_data(1); + + if (context->metrics_data == NULL) { + result = CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + + goto cleanup; + } + + context->metrics_data->resource_metrics[0] = \ + initialize_resource_metrics(resource_metrics_root, resource, 1); + + if (context->metrics_data->resource_metrics[0] == NULL) { + result = CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + + goto cleanup; + } + + context->metrics_data->resource_metrics[0]->scope_metrics[0] = \ + initialize_scope_metrics(scope_metrics_root, + get_metric_count(cmt)); + + if (context->metrics_data->resource_metrics[0]->scope_metrics[0] == NULL) { + result = CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + + goto cleanup; + } + + context->metrics_data->\ + resource_metrics[0]->\ + scope_metrics[0]->\ + scope = \ + initialize_instrumentation_scope( + scope_root, &result); + + if (result) { + result = CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + + goto cleanup; + } + +cleanup: + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + if (context != NULL) { + destroy_opentelemetry_context(context); + + context = NULL; + } + } + + return context; +} + +int append_sample_to_metric(struct cmt_opentelemetry_context *context, + Opentelemetry__Proto__Metrics__V1__Metric *metric, + struct cmt_map *map, + struct cmt_metric *sample, + size_t sample_index) +{ + size_t attribute_index; + size_t attribute_count; + Opentelemetry__Proto__Common__V1__KeyValue **attribute_list; + struct cmt_label *static_label; + struct cmt_map_label *label_value; + struct cmt_map_label *label_name; + void *data_point = NULL; + Opentelemetry__Proto__Common__V1__KeyValue *attribute; + struct cmt_histogram *histogram; + struct cmt_summary *summary; + int result; + struct cfl_list *head; + + attribute_count = cfl_list_size(&context->cmt->static_labels->list) + + cfl_list_size(&sample->labels); + + attribute_list = initialize_attribute_list(attribute_count); + + if (attribute_list == NULL) { + return CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + if (map->type == CMT_COUNTER || + map->type == CMT_GAUGE || + map->type == CMT_UNTYPED ) { + data_point = initialize_numerical_data_point(0, + cmt_metric_get_timestamp(sample), + cmt_metric_get_value(sample), + attribute_list, + attribute_count); + } + else if (map->type == CMT_SUMMARY) { + summary = (struct cmt_summary *) map->parent; + + data_point = initialize_summary_data_point(0, + cmt_metric_get_timestamp(sample), + cmt_summary_get_count_value(sample), + cmt_summary_get_sum_value(sample), + summary->quantiles_count, + summary->quantiles, + summary->quantiles_count, + sample->sum_quantiles, + attribute_list, + attribute_count); + } + else if (map->type == CMT_HISTOGRAM) { + histogram = (struct cmt_histogram *) map->parent; + + data_point = initialize_histogram_data_point(0, + cmt_metric_get_timestamp(sample), + cmt_metric_hist_get_count_value(sample), + cmt_metric_hist_get_sum_value(sample), + histogram->buckets->count + 1, + sample->hist_buckets, + histogram->buckets->count, + histogram->buckets->upper_bounds, + attribute_list, + attribute_count); + } + + if (data_point == NULL) { + destroy_attribute_list(attribute_list); + + return CMT_ENCODE_OPENTELEMETRY_DATA_POINT_INIT_ERROR; + } + + attribute_index = 0; + + cfl_list_foreach(head, &context->cmt->static_labels->list) { + static_label = cfl_list_entry(head, struct cmt_label, _head); + + attribute = initialize_string_attribute(static_label->key, + static_label->val); + + if (attribute == NULL) { + destroy_data_point(data_point, map->type); + + return CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + result = append_attribute_to_data_point(data_point, + map->type, + attribute, + attribute_index++); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) + { + destroy_data_point(data_point, map->type); + + return result; + } + } + + label_name = cfl_list_entry_first(&map->label_keys, struct cmt_map_label, _head); + + cfl_list_foreach(head, &sample->labels) { + label_value = cfl_list_entry(head, struct cmt_map_label, _head); + + attribute = initialize_string_attribute(label_name->name, + label_value->name); + + if (attribute == NULL) { + destroy_data_point(data_point, map->type); + + return CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + result = append_attribute_to_data_point(data_point, + map->type, + attribute, + attribute_index++); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) + { + destroy_data_point(data_point, map->type); + + return result; + } + + label_name = cfl_list_entry_next(&label_name->_head, struct cmt_map_label, + _head, &map->label_keys); + } + + result = append_data_point_to_metric(metric, (void *) data_point, sample_index); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + destroy_data_point(data_point, map->type); + + return result; + } + + return result; +} + +int pack_basic_type(struct cmt_opentelemetry_context *context, + struct cmt_map *map, + size_t *metric_index) +{ + int aggregation_temporality_type; + int monotonism_flag; + size_t sample_index; + size_t sample_count; + struct cmt_counter *counter; + struct cmt_metric *sample; + Opentelemetry__Proto__Metrics__V1__Metric *metric; + int result; + struct cfl_list *head; + + sample_count = 0; + + if (map->metric_static_set) { + sample_count++; + } + + sample_count += cfl_list_size(&map->metrics); + + if (sample_count == 0) { + return CMT_ENCODE_OPENTELEMETRY_SUCCESS; + } + + aggregation_temporality_type = OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_UNSPECIFIED; + monotonism_flag = CMT_FALSE; + + if (map->type == CMT_COUNTER) { + if (map->parent != NULL) { + counter = (struct cmt_counter *) map->parent; + + if (counter->aggregation_type == CMT_AGGREGATION_TYPE_DELTA) { + aggregation_temporality_type = OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_DELTA; + } + else if (counter->aggregation_type == CMT_AGGREGATION_TYPE_CUMULATIVE) { + aggregation_temporality_type = OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_CUMULATIVE; + } + + monotonism_flag = !counter->allow_reset; + } + } + + metric = initialize_metric(map->type, + map->opts->fqname, + map->opts->description, + map->unit, + monotonism_flag, + aggregation_temporality_type, + sample_count); + + if (metric == NULL) { + return CMT_ENCODE_OPENTELEMETRY_ALLOCATION_ERROR; + } + + sample_index = 0; + + if (map->metric_static_set) { + result = append_sample_to_metric(context, + metric, + map, + &map->metric, + sample_index++); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + destroy_metric(metric); + + return result; + } + } + + cfl_list_foreach(head, &map->metrics) { + sample = cfl_list_entry(head, struct cmt_metric, _head); + + result = append_sample_to_metric(context, + metric, + map, + sample, + sample_index++); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + destroy_metric(metric); + + return result; + } + } + + result = append_metric_to_scope_metrics( + context->\ + metrics_data->\ + resource_metrics[0]->\ + scope_metrics[0], + metric, + *metric_index); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + destroy_metric(metric); + + return result; + } + + (*metric_index)++; + + return result; +} + +static cfl_sds_t render_opentelemetry_context_to_sds( + struct cmt_opentelemetry_context *context) +{ + cfl_sds_t result_buffer; + size_t result_size; + + result_size = opentelemetry__proto__metrics__v1__metrics_data__get_packed_size( + context->metrics_data); + + result_buffer = cfl_sds_create_size(result_size); + + if(result_buffer != NULL) { + opentelemetry__proto__metrics__v1__metrics_data__pack( + context->metrics_data, + (uint8_t *) result_buffer); + + cfl_sds_set_len(result_buffer, result_size); + } + + return result_buffer; +} + +cfl_sds_t cmt_encode_opentelemetry_create(struct cmt *cmt) +{ + size_t metric_index; + struct cmt_opentelemetry_context *context; + struct cmt_histogram *histogram; + struct cmt_summary *summary; + struct cmt_untyped *untyped; + struct cmt_counter *counter; + int result; + struct cmt_gauge *gauge; + struct cfl_list *head; + cfl_sds_t buf; + + buf = NULL; + result = 0; + + context = initialize_opentelemetry_context(cmt); + + if (context == NULL) { + return NULL; + } + + metric_index = 0; + + if (result == CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + result = pack_basic_type(context, counter->map, &metric_index); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + result = pack_basic_type(context, gauge->map, &metric_index); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + result = pack_basic_type(context, untyped->map, &metric_index); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + result = pack_basic_type(context, summary->map, &metric_index); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + result = pack_basic_type(context, histogram->map, &metric_index); + + if (result != CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_OPENTELEMETRY_SUCCESS) { + buf = render_opentelemetry_context_to_sds(context); + } + + destroy_opentelemetry_context(context); + + return buf; +} + +void cmt_encode_opentelemetry_destroy(cfl_sds_t text) +{ + cfl_sds_destroy(text); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_encode_prometheus.c b/fluent-bit/lib/cmetrics/src/cmt_encode_prometheus.c new file mode 100644 index 00000000..287d701b --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_encode_prometheus.c @@ -0,0 +1,543 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdbool.h> + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_histogram.h> + +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_compat.h> + +#define PROM_FMT_VAL_FROM_VAL 0 +#define PROM_FMT_VAL_FROM_BUCKET_ID 1 +#define PROM_FMT_VAL_FROM_QUANTILE 2 +#define PROM_FMT_VAL_FROM_SUM 3 +#define PROM_FMT_VAL_FROM_COUNT 4 + +struct prom_fmt { + int metric_name; /* metric name already set ? */ + int brace_open; /* first brace open ? */ + int labels_count; /* number of labels aready added */ + int value_from; + + /* + * For value_from 'PROM_FMT_VAL_FROM_BUCKET_ID', the 'id' belongs to a bucket + * id position, if is 'PROM_FMT_VAL_FROM_QUANTILE' the value represents a + * sum_quantiles position. + */ + int id; +}; + +static void prom_fmt_init(struct prom_fmt *fmt) +{ + fmt->metric_name = CMT_FALSE; + fmt->brace_open = CMT_FALSE; + fmt->labels_count = 0; + fmt->value_from = PROM_FMT_VAL_FROM_VAL; + fmt->id = -1; +} + +/* + * Prometheus Exposition Format + * ---------------------------- + * https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md + */ + +static void metric_escape(cfl_sds_t *buf, cfl_sds_t description, bool escape_quote) +{ + int i; + size_t len; + + len = cfl_sds_len(description); + + for (i = 0; i < len; i++) { + switch (description[i]) { + case '\\': + cfl_sds_cat_safe(buf, "\\\\", 2); + break; + case '\n': + cfl_sds_cat_safe(buf, "\\n", 2); + break; + case '"': + if (escape_quote) { + cfl_sds_cat_safe(buf, "\\\"", 2); + break; + } + /* FALLTHROUGH */ + default: + cfl_sds_cat_safe(buf, description + i, 1); + break; + } + } +} + +static void metric_banner(cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + struct cmt_opts *opts; + + opts = map->opts; + + /* HELP */ + cfl_sds_cat_safe(buf, "# HELP ", 7); + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + + if (cfl_sds_len(opts->description) > 1 || opts->description[0] != ' ') { + /* only append description if it is not empty. the parser uses a single whitespace + * string to signal that no HELP was provided */ + cfl_sds_cat_safe(buf, " ", 1); + metric_escape(buf, opts->description, false); + } + cfl_sds_cat_safe(buf, "\n", 1); + + /* TYPE */ + cfl_sds_cat_safe(buf, "# TYPE ", 7); + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + + if (map->type == CMT_COUNTER) { + cfl_sds_cat_safe(buf, " counter\n", 9); + } + else if (map->type == CMT_GAUGE) { + cfl_sds_cat_safe(buf, " gauge\n", 7); + } + else if (map->type == CMT_SUMMARY) { + cfl_sds_cat_safe(buf, " summary\n", 9); + } + else if (map->type == CMT_HISTOGRAM) { + cfl_sds_cat_safe(buf, " histogram\n", 11); + } + else if (map->type == CMT_UNTYPED) { + cfl_sds_cat_safe(buf, " untyped\n", 9); + } +} + +static void append_metric_value(cfl_sds_t *buf, + struct cmt_map *map, + struct cmt_metric *metric, + struct prom_fmt *fmt, int add_timestamp) +{ + int len; + double val; + uint64_t ts; + char tmp[128]; + + /* + * Retrieve metric value + * --------------------- + * the formatter 'fmt->value_from' specifies from 'where' the value must + * be retrieved from, note the 'metric' structure contains one generic + * value field plus others associated to histograms. + */ + if (fmt->value_from == PROM_FMT_VAL_FROM_VAL) { + /* get 'normal' metric value */ + val = cmt_metric_get_value(metric); + } + else if (fmt->value_from == PROM_FMT_VAL_FROM_BUCKET_ID) { + /* retrieve the value from a bucket */ + val = cmt_metric_hist_get_value(metric, fmt->id); + } + else if (fmt->value_from == PROM_FMT_VAL_FROM_QUANTILE) { + /* retrieve the value from a bucket */ + val = cmt_summary_quantile_get_value(metric, fmt->id); + } + else { + if (map->type == CMT_HISTOGRAM) { + if (fmt->value_from == PROM_FMT_VAL_FROM_SUM) { + val = cmt_metric_hist_get_sum_value(metric); + } + else if (fmt->value_from == PROM_FMT_VAL_FROM_COUNT) { + val = cmt_metric_hist_get_count_value(metric); + } + } + else if (map->type == CMT_SUMMARY) { + if (fmt->value_from == PROM_FMT_VAL_FROM_SUM) { + val = cmt_summary_get_sum_value(metric); + } + else if (fmt->value_from == PROM_FMT_VAL_FROM_COUNT) { + val = cmt_summary_get_count_value(metric); + } + } + } + + if (add_timestamp) { + ts = cmt_metric_get_timestamp(metric); + + /* convert from nanoseconds to milliseconds */ + ts /= 1000000; + + len = snprintf(tmp, sizeof(tmp) - 1, " %.17g %" PRIu64 "\n", val, ts); + } + else { + len = snprintf(tmp, sizeof(tmp) - 1, " %.17g\n", val); + } + cfl_sds_cat_safe(buf, tmp, len); +} + +static int add_label(cfl_sds_t *buf, cfl_sds_t key, cfl_sds_t val) +{ + cfl_sds_cat_safe(buf, key, cfl_sds_len(key)); + cfl_sds_cat_safe(buf, "=\"", 2); + metric_escape(buf, val, true); + cfl_sds_cat_safe(buf, "\"", 1); + + return 1; +} + +static int add_static_labels(struct cmt *cmt, cfl_sds_t *buf) +{ + int count = 0; + int total = 0; + struct cfl_list *head; + struct cmt_label *label; + + total = cfl_list_size(&cmt->static_labels->list); + cfl_list_foreach(head, &cmt->static_labels->list) { + label = cfl_list_entry(head, struct cmt_label, _head); + + count += add_label(buf, label->key, label->val); + if (count < total) { + cfl_sds_cat_safe(buf, ",", 1); + } + } + + return count; +} + +static void format_metric(struct cmt *cmt, + cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric, int add_timestamp, + struct prom_fmt *fmt) +{ + int i; + int static_labels = 0; + int defined_labels = 0; + struct cmt_map_label *label_k; + struct cmt_map_label *label_v; + struct cfl_list *head; + struct cmt_opts *opts; + + opts = map->opts; + + /* Metric info */ + if (!fmt->metric_name) { + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + } + + /* Static labels */ + static_labels = cmt_labels_count(cmt->static_labels); + cfl_list_foreach(head, &metric->labels) { + label_v = cfl_list_entry(head, struct cmt_map_label, _head); + if (strlen(label_v->name)) { + defined_labels++; + } + } + + if (!fmt->brace_open && (static_labels + defined_labels > 0)) { + cfl_sds_cat_safe(buf, "{", 1); + } + + if (static_labels > 0) { + /* if some labels were added before, add the separator */ + if (fmt->labels_count > 0) { + cfl_sds_cat_safe(buf, ",", 1); + } + fmt->labels_count += add_static_labels(cmt, buf); + } + + /* Append api defined labels */ + if (defined_labels > 0) { + if (fmt->labels_count > 0) { + cfl_sds_cat_safe(buf, ",", 1); + } + + i = 1; + label_k = cfl_list_entry_first(&map->label_keys, struct cmt_map_label, _head); + cfl_list_foreach(head, &metric->labels) { + label_v = cfl_list_entry(head, struct cmt_map_label, _head); + + if (strlen(label_v->name)) { + fmt->labels_count += add_label(buf, label_k->name, label_v->name); + if (i < defined_labels) { + cfl_sds_cat_safe(buf, ",", 1); + } + + i++; + } + + label_k = cfl_list_entry_next(&label_k->_head, struct cmt_map_label, + _head, &map->label_keys); + } + } + + if (fmt->labels_count > 0) { + cfl_sds_cat_safe(buf, "}", 1); + } + + append_metric_value(buf, map, metric, fmt, add_timestamp); +} + +static cfl_sds_t bucket_value_to_string(double val) +{ + int len; + cfl_sds_t str; + + str = cfl_sds_create_size(64); + if (!str) { + return NULL; + } + + len = snprintf(str, 64, "%g", val); + cfl_sds_len_set(str, len); + + if (!strchr(str, '.')) { + cfl_sds_cat_safe(&str, ".0", 2); + } + + return str; +} + +static void format_histogram_bucket(struct cmt *cmt, + cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric, int add_timestamp) +{ + int i; + cfl_sds_t val; + struct cmt_histogram *histogram; + struct cmt_histogram_buckets *bucket; + struct cmt_opts *opts; + struct prom_fmt fmt = {0}; + + histogram = (struct cmt_histogram *) map->parent; + bucket = histogram->buckets; + opts = map->opts; + + for (i = 0; i <= bucket->count; i++) { + /* metric name */ + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + cfl_sds_cat_safe(buf, "_bucket", 7); + + /* upper bound */ + cfl_sds_cat_safe(buf, "{le=\"", 5); + + if (i < bucket->count) { + val = bucket_value_to_string(bucket->upper_bounds[i]); + cfl_sds_cat_safe(buf, val, cfl_sds_len(val)); + cfl_sds_destroy(val); + } + else { + cfl_sds_cat_safe(buf, "+Inf", 4); + } + cfl_sds_cat_safe(buf, "\"", 1); + + /* configure formatter */ + fmt.metric_name = CMT_TRUE; + fmt.brace_open = CMT_TRUE; + fmt.labels_count = 1; + fmt.value_from = PROM_FMT_VAL_FROM_BUCKET_ID; + fmt.id = i; + + /* append metric labels, value and timestamp */ + format_metric(cmt, buf, map, metric, add_timestamp, &fmt); + } + + /* sum */ + prom_fmt_init(&fmt); + fmt.metric_name = CMT_TRUE; + fmt.value_from = PROM_FMT_VAL_FROM_SUM; + + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + cfl_sds_cat_safe(buf, "_sum", 4); + format_metric(cmt, buf, map, metric, add_timestamp, &fmt); + + /* count */ + fmt.labels_count = 0; + fmt.value_from = PROM_FMT_VAL_FROM_COUNT; + + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + cfl_sds_cat_safe(buf, "_count", 6); + format_metric(cmt, buf, map, metric, add_timestamp, &fmt); +} + +static void format_summary_quantiles(struct cmt *cmt, + cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric, int add_timestamp) +{ + int i; + cfl_sds_t val; + struct cmt_summary *summary; + struct cmt_opts *opts; + struct prom_fmt fmt = {0}; + + summary = (struct cmt_summary *) map->parent; + opts = map->opts; + + if (metric->sum_quantiles_set) { + for (i = 0; i < summary->quantiles_count; i++) { + /* metric name */ + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + + /* quantiles */ + cfl_sds_cat_safe(buf, "{quantile=\"", 11); + val = bucket_value_to_string(summary->quantiles[i]); + cfl_sds_cat_safe(buf, val, cfl_sds_len(val)); + cfl_sds_destroy(val); + cfl_sds_cat_safe(buf, "\"", 1); + + /* configure formatter */ + fmt.metric_name = CMT_TRUE; + fmt.brace_open = CMT_TRUE; + fmt.labels_count = 1; + fmt.value_from = PROM_FMT_VAL_FROM_QUANTILE; + fmt.id = i; + + /* append metric labels, value and timestamp */ + format_metric(cmt, buf, map, metric, add_timestamp, &fmt); + } + } + + /* sum */ + prom_fmt_init(&fmt); + fmt.metric_name = CMT_TRUE; + fmt.value_from = PROM_FMT_VAL_FROM_SUM; + + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + cfl_sds_cat_safe(buf, "_sum", 4); + format_metric(cmt, buf, map, metric, add_timestamp, &fmt); + + /* count */ + fmt.labels_count = 0; + fmt.value_from = PROM_FMT_VAL_FROM_COUNT; + + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + cfl_sds_cat_safe(buf, "_count", 6); + format_metric(cmt, buf, map, metric, add_timestamp, &fmt); +} + +static void format_metrics(struct cmt *cmt, cfl_sds_t *buf, struct cmt_map *map, + int add_timestamp) +{ + int banner_set = CMT_FALSE; + struct cfl_list *head; + struct cmt_metric *metric; + struct prom_fmt fmt = {0}; + + /* Simple metric, no labels */ + if (map->metric_static_set) { + metric_banner(buf, map, &map->metric); + banner_set = CMT_TRUE; + + if (map->type == CMT_HISTOGRAM) { + /* Histogram needs to format the buckets, one line per bucket */ + format_histogram_bucket(cmt, buf, map, &map->metric, add_timestamp); + } + else if (map->type == CMT_SUMMARY) { + /* Histogram needs to format the buckets, one line per bucket */ + format_summary_quantiles(cmt, buf, map, &map->metric, add_timestamp); + } + else { + prom_fmt_init(&fmt); + format_metric(cmt, buf, map, &map->metric, add_timestamp, &fmt); + } + } + + if (cfl_list_size(&map->metrics) > 0) { + metric = cfl_list_entry_first(&map->metrics, struct cmt_metric, _head); + if (!banner_set) { + metric_banner(buf, map, metric); + } + } + + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + + /* Format the metric based on its type */ + if (map->type == CMT_HISTOGRAM) { + /* Histogram needs to format the buckets, one line per bucket */ + format_histogram_bucket(cmt, buf, map, metric, add_timestamp); + } + else if (map->type == CMT_SUMMARY) { + format_summary_quantiles(cmt, buf, map, metric, add_timestamp); + } + else { + prom_fmt_init(&fmt); + format_metric(cmt, buf, map, metric, add_timestamp, &fmt); + } + } +} + +/* Format all the registered metrics in Prometheus Text format */ +cfl_sds_t cmt_encode_prometheus_create(struct cmt *cmt, int add_timestamp) +{ + cfl_sds_t buf; + struct cfl_list *head; + struct cmt_counter *counter; + struct cmt_gauge *gauge; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + struct cmt_untyped *untyped; + + /* Allocate a 1KB of buffer */ + buf = cfl_sds_create_size(1024); + if (!buf) { + return NULL; + } + + /* Counters */ + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + format_metrics(cmt, &buf, counter->map, add_timestamp); + } + + /* Gauges */ + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + format_metrics(cmt, &buf, gauge->map, add_timestamp); + } + + /* Summaries */ + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + format_metrics(cmt, &buf, summary->map, add_timestamp); + } + + /* Histograms */ + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + format_metrics(cmt, &buf, histogram->map, add_timestamp); + } + + /* Untyped */ + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + format_metrics(cmt, &buf, untyped->map, add_timestamp); + } + + return buf; +} + +void cmt_encode_prometheus_destroy(cfl_sds_t text) +{ + cfl_sds_destroy(text); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_encode_prometheus_remote_write.c b/fluent-bit/lib/cmetrics/src/cmt_encode_prometheus_remote_write.c new file mode 100644 index 00000000..2aede25e --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_encode_prometheus_remote_write.c @@ -0,0 +1,1131 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_encode_prometheus_remote_write.h> + +#define SYNTHETIC_METRIC_SUMMARY_COUNT_SEQUENCE_DELTA 10000000 +#define SYNTHETIC_METRIC_SUMMARY_SUM_SEQUENCE_DELTA 100000000 + +#define SYNTHETIC_METRIC_HISTOGRAM_COUNT_SEQUENCE_DELTA 10000000 +#define SYNTHETIC_METRIC_HISTOGRAM_SUM_SEQUENCE_DELTA 100000000 + +static cfl_sds_t render_remote_write_context_to_sds( + struct cmt_prometheus_remote_write_context *context); + +static void destroy_prometheus_label_list(Prometheus__Label **label_list, + size_t entry_count); + +static void destroy_prometheus_sample_list(Prometheus__Sample **sample_list, + size_t entry_count); + +static void cmt_destroy_prometheus_remote_write_context( + struct cmt_prometheus_remote_write_context *context); + +static uint64_t calculate_label_set_hash(struct cfl_list *label_values, uint64_t seed); + +static size_t count_metrics_with_matching_label_set(struct cfl_list *metrics, + uint64_t sequence_number, + uint64_t desired_hash); + +static int append_entry_to_prometheus_label_list(Prometheus__Label **label_list, + size_t *index, + char *name, + char *value); + +static int set_up_time_series_for_label_set( + struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map, + struct cmt_metric *metric, + struct cmt_prometheus_time_series **time_series); + +static int pack_metric_metadata(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map, + struct cmt_metric *metric); + +static int append_metric_to_timeseries(struct cmt_prometheus_time_series *time_series, + struct cmt_metric *metric); + +static int pack_basic_type(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map); + +static void destroy_label(struct cmt_map_label *instance) +{ + if (instance != NULL) { + if (instance->name != NULL) { + cfl_sds_destroy(instance->name); + } + + free(instance); + } +} + +static struct cmt_map_label *create_label(char *caption) +{ + struct cmt_map_label *instance; + + instance = calloc(1, sizeof(struct cmt_map_label)); + + if (instance != NULL) { + if (caption != NULL) { + instance->name = cfl_sds_create(caption); + + if (instance->name == NULL) { + cmt_errno(); + + free(instance); + + instance = NULL; + } + } + } + + return instance; +} + +cfl_sds_t render_remote_write_context_to_sds( + struct cmt_prometheus_remote_write_context *context) +{ + size_t write_request_size; + struct cmt_prometheus_time_series *time_series_entry; + struct cmt_prometheus_metric_metadata *metadata_entry; + cfl_sds_t result_buffer; + size_t entry_index; + struct cfl_list *head; + + context->write_request.n_timeseries = cfl_list_size(&context->time_series_entries); + context->write_request.n_metadata = cfl_list_size(&context->metadata_entries); + + context->write_request.timeseries = calloc(context->write_request.n_timeseries, + sizeof(Prometheus__TimeSeries *)); + + if (context->write_request.timeseries == NULL) { + cmt_errno(); + + return NULL; + } + + context->write_request.metadata = calloc(context->write_request.n_metadata, + sizeof(Prometheus__TimeSeries *)); + + if (context->write_request.metadata == NULL) { + cmt_errno(); + + free(context->write_request.timeseries); + + return NULL; + } + + entry_index = 0; + + cfl_list_foreach(head, &context->time_series_entries) { + time_series_entry = cfl_list_entry(head, struct cmt_prometheus_time_series, _head); + + context->write_request.timeseries[entry_index++] = &time_series_entry->data; + } + + entry_index = 0; + + cfl_list_foreach(head, &context->metadata_entries) { + metadata_entry = cfl_list_entry(head, struct cmt_prometheus_metric_metadata, _head); + + context->write_request.metadata[entry_index++] = &metadata_entry->data; + } + + write_request_size = prometheus__write_request__get_packed_size(&context->write_request); + + result_buffer = cfl_sds_create_size(write_request_size); + + if(result_buffer != NULL) { + prometheus__write_request__pack(&context->write_request, (uint8_t *) result_buffer); + + cfl_sds_set_len(result_buffer, write_request_size); + } + + free(context->write_request.timeseries); + + free(context->write_request.metadata); + + return result_buffer; +} + +void cmt_destroy_prometheus_remote_write_context( + struct cmt_prometheus_remote_write_context *context) +{ + struct cmt_prometheus_time_series *time_series_entry; + struct cmt_prometheus_metric_metadata *metadata_entry; + struct cfl_list *head; + struct cfl_list *tmp; + + cfl_list_foreach_safe(head, tmp, &context->time_series_entries) { + time_series_entry = cfl_list_entry(head, struct cmt_prometheus_time_series, _head); + + if (time_series_entry->data.labels != NULL) { + destroy_prometheus_label_list(time_series_entry->data.labels, + time_series_entry->data.n_labels); + + time_series_entry->data.labels = NULL; + } + + if (time_series_entry->data.samples != NULL) { + destroy_prometheus_sample_list(time_series_entry->data.samples, + time_series_entry->data.n_samples); + + time_series_entry->data.samples = NULL; + } + + cfl_list_del(&time_series_entry->_head); + + free(time_series_entry); + } + + cfl_list_foreach_safe(head, tmp, &context->metadata_entries) { + metadata_entry = cfl_list_entry(head, struct cmt_prometheus_metric_metadata, _head); + + if (metadata_entry->data.metric_family_name != NULL) { + cfl_sds_destroy(metadata_entry->data.metric_family_name); + } + + if (metadata_entry->data.help != NULL) { + cfl_sds_destroy(metadata_entry->data.help); + } + + if (metadata_entry->data.unit != NULL) { + cfl_sds_destroy(metadata_entry->data.unit); + } + + cfl_list_del(&metadata_entry->_head); + + free(metadata_entry); + } +} + +uint64_t calculate_label_set_hash(struct cfl_list *label_values, uint64_t seed) +{ + struct cmt_map_label *label_value; + cfl_hash_state_t state; + struct cfl_list *head; + + cfl_hash_64bits_reset(&state); + cfl_hash_64bits_update(&state, &seed, sizeof(uint64_t)); + + cfl_list_foreach(head, label_values) { + label_value = cfl_list_entry(head, struct cmt_map_label, _head); + + if (label_value->name == NULL) { + cfl_hash_64bits_update(&state, "_NULL_", 6); + } + else { + cfl_hash_64bits_update(&state, label_value->name, cfl_sds_len(label_value->name)); + } + } + + return cfl_hash_64bits_digest(&state); +} + +size_t count_metrics_with_matching_label_set(struct cfl_list *metrics, + uint64_t sequence_number, + uint64_t desired_hash) +{ + uint64_t label_set_hash; + size_t matches; + struct cmt_metric *metric; + struct cfl_list *head; + + matches = 0; + + cfl_list_foreach(head, metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + + label_set_hash = calculate_label_set_hash(&metric->labels, sequence_number); + + if (label_set_hash == desired_hash) { + matches++; + } + } + + return matches; +} + +int append_entry_to_prometheus_label_list(Prometheus__Label **label_list, + size_t *index, + char *name, + char *value) +{ + label_list[*index] = calloc(1, sizeof(Prometheus__Label)); + + if (label_list[*index] == NULL) { + cmt_errno(); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + prometheus__label__init(label_list[*index]); + + label_list[*index]->name = cfl_sds_create(name); + + if (label_list[*index]->name == NULL) { + free(label_list[*index]); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + label_list[*index]->value = cfl_sds_create(value); + + if (label_list[*index]->value == NULL) { + cfl_sds_destroy(label_list[*index]->name); + free(label_list[*index]); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + (*index)++; + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; +} + +void destroy_prometheus_sample_list(Prometheus__Sample **sample_list, + size_t entry_count) +{ + size_t index; + + if (sample_list != NULL) { + for (index = 0 ; index < entry_count ; index++) { + if (sample_list[index] != NULL) { + free(sample_list[index]); + sample_list[index] = NULL; + } + } + + free(sample_list); + } +} + +void destroy_prometheus_label_list(Prometheus__Label **label_list, + size_t entry_count) +{ + size_t index; + + if (label_list != NULL) { + for (index = 0 ; index < entry_count ; index++) { + if (label_list[index] != NULL) { + if (label_list[index]->name != NULL) { + cfl_sds_destroy(label_list[index]->name); + label_list[index]->name = NULL; + } + + if (label_list[index]->value != NULL) { + cfl_sds_destroy(label_list[index]->value); + label_list[index]->value = NULL; + } + + free(label_list[index]); + label_list[index] = NULL; + } + } + + free(label_list); + } +} + +int set_up_time_series_for_label_set(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map, + struct cmt_metric *metric, + struct cmt_prometheus_time_series **time_series) +{ + uint8_t time_series_match_found; + size_t label_set_hash_matches; + struct cmt_prometheus_time_series *time_series_entry; + uint64_t label_set_hash; + struct cmt_label *static_label; + size_t label_index; + size_t label_count; + struct cmt_map_label *label_value; + struct cmt_map_label *label_name; + Prometheus__Label **label_list; + Prometheus__Sample **value_list; + int result; + struct cfl_list *head; + + label_set_hash = calculate_label_set_hash(&metric->labels, context->sequence_number); + + /* Determine if there is an existing time series for this label set */ + time_series_match_found = CMT_FALSE; + + cfl_list_foreach(head, &context->time_series_entries) { + time_series_entry = cfl_list_entry(head, struct cmt_prometheus_time_series, _head); + + if (time_series_entry->label_set_hash == label_set_hash) { + time_series_match_found = CMT_TRUE; + + break; + } + } + + if (time_series_match_found == CMT_TRUE) { + *time_series = time_series_entry; + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + } + + /* Find out how many samples share these label values */ + label_set_hash_matches = count_metrics_with_matching_label_set(&map->metrics, + context->sequence_number, + label_set_hash); + + if (label_set_hash_matches == 0) + { + label_set_hash_matches++; + } + + /* Allocate the memory required for the label and value lists, we need to add + * one for the fixed __name__ label + */ + label_count = cfl_list_size(&context->cmt->static_labels->list) + + cfl_list_size(&metric->labels) + + 1; + + + time_series_entry = calloc(1, sizeof(struct cmt_prometheus_time_series)); + + if (time_series_entry == NULL) { + cmt_errno(); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + label_list = calloc(label_count, sizeof(Prometheus__Label *)); + + if (label_list == NULL) { + cmt_errno(); + + free(time_series_entry); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + value_list = calloc(label_set_hash_matches, sizeof(Prometheus__Sample *)); + + if (value_list == NULL) { + cmt_errno(); + + free(time_series_entry); + free(label_list); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + /* Initialize the time series */ + prometheus__time_series__init(&time_series_entry->data); + + time_series_entry->data.n_labels = label_count; + time_series_entry->data.labels = label_list; + time_series_entry->data.n_samples = label_set_hash_matches; + time_series_entry->data.samples = value_list; + + time_series_entry->label_set_hash = label_set_hash; + time_series_entry->entries_set = 0; + + /* Initialize the label list */ + label_index = 0; + + /* Add the __name__ label */ + result = append_entry_to_prometheus_label_list(label_list, + &label_index, + "__name__", + map->opts->fqname); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) + { + free(time_series_entry); + free(label_list); + free(value_list); + + return result; + } + + /* Add the static labels */ + result = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + cfl_list_foreach(head, &context->cmt->static_labels->list) { + static_label = cfl_list_entry(head, struct cmt_label, _head); + + result = append_entry_to_prometheus_label_list(label_list, + &label_index, + static_label->key, + static_label->val); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) + { + break; + } + } + + /* Add the specific labels */ + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS && label_count > 0) { + label_name = cfl_list_entry_first(&map->label_keys, struct cmt_map_label, _head); + + cfl_list_foreach(head, &metric->labels) { + label_value = cfl_list_entry(head, struct cmt_map_label, _head); + + result = append_entry_to_prometheus_label_list(label_list, + &label_index, + label_name->name, + label_value->name); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) + { + break; + } + + label_name = cfl_list_entry_next(&label_name->_head, struct cmt_map_label, + _head, &map->label_keys); + } + } + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + destroy_prometheus_label_list(label_list, label_index); + free(time_series_entry); + free(value_list); + + return result; + } + + /* Add the time series to the context so we can find it when we try to format + * a metric with these same labels; + */ + cfl_list_add(&time_series_entry->_head, &context->time_series_entries); + + *time_series = time_series_entry; + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; +} + + +int pack_metric_metadata(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map, + struct cmt_metric *metric) +{ + struct cmt_prometheus_metric_metadata *metadata_entry; + + metadata_entry = calloc(1, sizeof(struct cmt_prometheus_metric_metadata)); + + if (metadata_entry == NULL) { + cmt_errno(); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + prometheus__metric_metadata__init(&metadata_entry->data); + + if (map->type == CMT_COUNTER) { + metadata_entry->data.type = PROMETHEUS__METRIC_METADATA__METRIC_TYPE__COUNTER; + } + else if (map->type == CMT_GAUGE) { + metadata_entry->data.type = PROMETHEUS__METRIC_METADATA__METRIC_TYPE__GAUGE; + } + else if (map->type == CMT_UNTYPED) { + metadata_entry->data.type = PROMETHEUS__METRIC_METADATA__METRIC_TYPE__UNKNOWN; + } + else if (map->type == CMT_SUMMARY) { + metadata_entry->data.type = PROMETHEUS__METRIC_METADATA__METRIC_TYPE__SUMMARY; + } + else { + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_UNEXPECTED_METRIC_TYPE; + } + + if (map->opts->fqname == NULL) { + metadata_entry->data.metric_family_name = cfl_sds_create(""); + } + else { + metadata_entry->data.metric_family_name = cfl_sds_create(map->opts->fqname); + } + + if (metadata_entry->data.metric_family_name == NULL) { + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + if (map->opts->description == NULL) { + metadata_entry->data.help = cfl_sds_create(""); + } + else { + metadata_entry->data.help = cfl_sds_create(map->opts->description); + } + + if (metadata_entry->data.help == NULL) { + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + if (map->unit == NULL) { + metadata_entry->data.unit = cfl_sds_create(""); + } + else { + metadata_entry->data.unit = cfl_sds_create(map->unit); + } + + if (metadata_entry->data.unit == NULL) { + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + cfl_list_add(&metadata_entry->_head, &context->metadata_entries); + + return 0; +} + +int append_metric_to_timeseries(struct cmt_prometheus_time_series *time_series, + struct cmt_metric *metric) +{ + uint64_t ts; + Prometheus__Sample *sample; + + sample = calloc(1, sizeof(Prometheus__Sample)); + + if (sample == NULL) { + cmt_errno(); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + prometheus__sample__init(sample); + + sample->value = cmt_metric_get_value(metric); + + ts = cmt_metric_get_timestamp(metric); + sample->timestamp = ts / 1000000; + time_series->data.samples[time_series->entries_set++] = sample; + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; +} + +int pack_basic_metric_sample(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map, + struct cmt_metric *metric, + int add_metadata) +{ + struct cmt_prometheus_time_series *time_series; + int result; + + result = set_up_time_series_for_label_set(context, map, metric, &time_series); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + return result; + } + + if (add_metadata == CMT_TRUE) { + result = pack_metric_metadata(context, map, metric); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + return result; + } + } + + return append_metric_to_timeseries(time_series, metric); +} + +int pack_basic_type(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map) +{ + int add_metadata; + struct cmt_metric *metric; + int result; + struct cfl_list *head; + + context->sequence_number++; + add_metadata = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ADD_METADATA; + + if (map->metric_static_set == CMT_TRUE) { + result = pack_basic_metric_sample(context, map, &map->metric, add_metadata); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + return result; + } + } + + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + + result = pack_basic_metric_sample(context, map, metric, add_metadata); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + return result; + } + + if (add_metadata == CMT_TRUE) { + add_metadata = CMT_FALSE; + } + } + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; +} + +int pack_complex_metric_sample(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map, + struct cmt_metric *metric, + int add_metadata) +{ + size_t original_label_value_count = 0; + cfl_sds_t synthetized_metric_name; + cfl_sds_t original_metric_name; + size_t label_value_count = 0; + cfl_sds_t additional_label_caption; + size_t label_key_count; + struct cmt_map_label *additional_label; + struct cmt_metric dummy_metric; + struct cmt_prometheus_time_series *time_series; + struct cmt_map_label *dummy_label; + struct cmt_histogram *histogram; + struct cmt_summary *summary; + int result; + size_t index; + + additional_label_caption = cfl_sds_create_len(NULL, 128); + + if (additional_label_caption == NULL) { + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + synthetized_metric_name = cfl_sds_create_len(NULL, + cfl_sds_alloc(map->opts->fqname) + 16); + + if (synthetized_metric_name == NULL) { + cfl_sds_destroy(additional_label_caption); + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + original_metric_name = map->opts->fqname; + + result = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + memset(&dummy_metric, 0, sizeof(struct cmt_metric)); + memcpy(&dummy_metric.labels, &metric->labels, sizeof(struct cfl_list)); + + dummy_metric.timestamp = metric->timestamp; + + if (map->type == CMT_SUMMARY) { + summary = (struct cmt_summary *) map->parent; + + context->sequence_number += SYNTHETIC_METRIC_SUMMARY_COUNT_SEQUENCE_DELTA; + + map->opts->fqname = synthetized_metric_name; + + cfl_sds_len_set(synthetized_metric_name, + snprintf(synthetized_metric_name, + cfl_sds_alloc(synthetized_metric_name) -1, + "%s_count", + original_metric_name)); + + cmt_metric_set(&dummy_metric, + dummy_metric.timestamp, + cmt_summary_get_count_value(metric)); + + result = set_up_time_series_for_label_set(context, map, metric, &time_series); + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (add_metadata == CMT_TRUE) { + result = pack_metric_metadata(context, map, &dummy_metric); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + result = append_metric_to_timeseries(time_series, &dummy_metric); + } + } + + context->sequence_number -= SYNTHETIC_METRIC_SUMMARY_COUNT_SEQUENCE_DELTA; + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + context->sequence_number += SYNTHETIC_METRIC_SUMMARY_SUM_SEQUENCE_DELTA; + cfl_sds_len_set(synthetized_metric_name, + snprintf(synthetized_metric_name, + cfl_sds_alloc(synthetized_metric_name) -1, + "%s_sum", + original_metric_name)); + + cmt_metric_set(&dummy_metric, + dummy_metric.timestamp, + cmt_summary_get_sum_value(metric)); + + result = set_up_time_series_for_label_set(context, map, metric, &time_series); + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (add_metadata == CMT_TRUE) { + result = pack_metric_metadata(context, map, &dummy_metric); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + result = append_metric_to_timeseries(time_series, &dummy_metric); + } + } + + context->sequence_number -= SYNTHETIC_METRIC_SUMMARY_SUM_SEQUENCE_DELTA; + } + + map->opts->fqname = original_metric_name; + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + label_key_count = cfl_list_size(&map->label_keys); + original_label_value_count = cfl_list_size(&metric->labels); + + for (label_value_count = original_label_value_count ; + result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS && + label_value_count < label_key_count; + label_value_count++) { + dummy_label = create_label(NULL); + + if (dummy_label == NULL) { + result = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + cfl_list_add(&dummy_label->_head, &metric->labels); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + additional_label = cfl_list_entry_last(&metric->labels, struct cmt_map_label, _head); + + if (additional_label == NULL) { + result = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + additional_label->name = (cfl_sds_t) additional_label_caption; + + for(index = 0 ; + result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS && + index < summary->quantiles_count ; + index++) { + cfl_sds_len_set(additional_label_caption, + snprintf(additional_label_caption, + cfl_sds_alloc(additional_label_caption) - 1, + "%.17g", summary->quantiles[index])); + + dummy_metric.val = cmt_math_d64_to_uint64(cmt_summary_quantile_get_value(metric, index)); + + result = set_up_time_series_for_label_set(context, map, metric, &time_series); + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (add_metadata == CMT_TRUE) { + result = pack_metric_metadata(context, map, &dummy_metric); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + result = append_metric_to_timeseries(time_series, &dummy_metric); + } + } + } + } + } + } + } + else if (map->type == CMT_HISTOGRAM) { + histogram = (struct cmt_histogram *) map->parent; + + context->sequence_number += SYNTHETIC_METRIC_HISTOGRAM_COUNT_SEQUENCE_DELTA; + + map->opts->fqname = synthetized_metric_name; + + cfl_sds_len_set(synthetized_metric_name, + snprintf(synthetized_metric_name, + cfl_sds_alloc(synthetized_metric_name) -1, + "%s_count", + original_metric_name)); + + cmt_metric_set(&dummy_metric, + dummy_metric.timestamp, + cmt_metric_hist_get_count_value(metric)); + + result = set_up_time_series_for_label_set(context, map, metric, &time_series); + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (add_metadata == CMT_TRUE) { + result = pack_metric_metadata(context, map, &dummy_metric); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + result = append_metric_to_timeseries(time_series, &dummy_metric); + } + } + + context->sequence_number -= SYNTHETIC_METRIC_HISTOGRAM_COUNT_SEQUENCE_DELTA; + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + context->sequence_number += SYNTHETIC_METRIC_HISTOGRAM_SUM_SEQUENCE_DELTA; + + cfl_sds_len_set(synthetized_metric_name, + snprintf(synthetized_metric_name, + cfl_sds_alloc(synthetized_metric_name) -1, + "%s_sum", + original_metric_name)); + + cmt_metric_set(&dummy_metric, + dummy_metric.timestamp, + cmt_metric_hist_get_sum_value(metric)); + + result = set_up_time_series_for_label_set(context, map, metric, &time_series); + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (add_metadata == CMT_TRUE) { + result = pack_metric_metadata(context, map, &dummy_metric); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + result = append_metric_to_timeseries(time_series, &dummy_metric); + } + } + + context->sequence_number -= SYNTHETIC_METRIC_HISTOGRAM_SUM_SEQUENCE_DELTA; + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + cfl_sds_len_set(synthetized_metric_name, + snprintf(synthetized_metric_name, + cfl_sds_alloc(synthetized_metric_name) - 1, + "%s_bucket", + original_metric_name)); + + label_key_count = cfl_list_size(&map->label_keys); + original_label_value_count = cfl_list_size(&metric->labels); + + for (label_value_count = original_label_value_count ; + result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS && + label_value_count < label_key_count; + label_value_count++) { + dummy_label = create_label(NULL); + + if (dummy_label == NULL) { + result = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + cfl_list_add(&dummy_label->_head, &metric->labels); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + additional_label = cfl_list_entry_last(&metric->labels, struct cmt_map_label, _head); + + additional_label->name = (cfl_sds_t) additional_label_caption; + + for(index = 0 ; + result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS && + index <= histogram->buckets->count ; + index++) { + if (index < histogram->buckets->count) { + cfl_sds_len_set(additional_label_caption, + snprintf(additional_label_caption, + cfl_sds_alloc(additional_label_caption) - 1, + "%.17g", histogram->buckets->upper_bounds[index])); + } + else { + cfl_sds_len_set(additional_label_caption, + snprintf(additional_label_caption, + cfl_sds_alloc(additional_label_caption) - 1, + "+Inf")); + } + + + dummy_metric.val = cmt_math_d64_to_uint64(cmt_metric_hist_get_value(metric, index)); + + result = set_up_time_series_for_label_set(context, map, metric, &time_series); + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (add_metadata == CMT_TRUE) { + result = pack_metric_metadata(context, map, &dummy_metric); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + result = append_metric_to_timeseries(time_series, &dummy_metric); + } + } + } + } + } + + map->opts->fqname = original_metric_name; + } + + for ( ; + label_value_count > original_label_value_count; + label_value_count--) { + additional_label = cfl_list_entry_last(&metric->labels, struct cmt_map_label, _head); + + if (additional_label != NULL) { + cfl_list_del(&additional_label->_head); + + if (additional_label->name == additional_label_caption) { + additional_label_caption = NULL; + } + + destroy_label(additional_label); + } + } + + if (additional_label_caption != NULL) { + cfl_sds_destroy(additional_label_caption); + } + + cfl_sds_destroy(synthetized_metric_name); + + return result; +} + +int pack_complex_type(struct cmt_prometheus_remote_write_context *context, + struct cmt_map *map) +{ + struct cmt_map_label additional_label; + int add_metadata; + struct cmt_metric *metric; + int result; + struct cfl_list *head; + + context->sequence_number++; + + add_metadata = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_ADD_METADATA; + result = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + if (map->type == CMT_SUMMARY) { + additional_label.name = (cfl_sds_t) "quantile"; + } + else if (map->type == CMT_HISTOGRAM) { + additional_label.name = (cfl_sds_t) "le"; + } + + cfl_list_add(&additional_label._head, &map->label_keys); + + if (map->metric_static_set == CMT_TRUE) { + result = pack_complex_metric_sample(context, map, &map->metric, add_metadata); + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + + result = pack_complex_metric_sample(context, map, metric, add_metadata); + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (add_metadata == CMT_TRUE) { + add_metadata = CMT_FALSE; + } + } + } + } + + if (map->type == CMT_SUMMARY || + map->type == CMT_HISTOGRAM) { + cfl_list_del(&additional_label._head); + } + + return CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; +} + +/* Format all the registered metrics in Prometheus Text format */ +cfl_sds_t cmt_encode_prometheus_remote_write_create(struct cmt *cmt) +{ + struct cmt_histogram *histogram; + struct cmt_prometheus_remote_write_context context; + struct cmt_untyped *untyped; + struct cmt_counter *counter; + struct cmt_summary *summary; + int result; + struct cmt_gauge *gauge; + struct cfl_list *head; + cfl_sds_t buf; + + result = CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + buf = NULL; + + memset(&context, 0, sizeof(struct cmt_prometheus_remote_write_context)); + + prometheus__write_request__init(&context.write_request); + + context.cmt = cmt; + + cfl_list_init(&context.time_series_entries); + cfl_list_init(&context.metadata_entries); + + /* Counters */ + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + result = pack_basic_type(&context, counter->map); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + break; + } + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + /* Gauges */ + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + result = pack_basic_type(&context, gauge->map); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + /* Untyped */ + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + pack_basic_type(&context, untyped->map); + } + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + /* Summaries */ + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + result = pack_complex_type(&context, summary->map); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + /* Histograms */ + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + result = pack_complex_type(&context, histogram->map); + + if (result != CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + break; + } + } + } + + if (result == CMT_ENCODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + buf = render_remote_write_context_to_sds(&context); + } + + cmt_destroy_prometheus_remote_write_context(&context); + + return buf; +} + +void cmt_encode_prometheus_remote_write_destroy(cfl_sds_t text) +{ + cfl_sds_destroy(text); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_encode_splunk_hec.c b/fluent-bit/lib/cmetrics/src/cmt_encode_splunk_hec.c new file mode 100644 index 00000000..a2db9ae8 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_encode_splunk_hec.c @@ -0,0 +1,710 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_time.h> +#include <cmetrics/cmt_compat.h> +#include <cmetrics/cmt_encode_splunk_hec.h> + +static cfl_sds_t double_to_string(double val) +{ + int len; + cfl_sds_t str; + + str = cfl_sds_create_size(64); + if (!str) { + return NULL; + } + + len = snprintf(str, 64, "%g", val); + if (strstr(str, "e+")) { + len = snprintf(str, 64, "%e", val); + cfl_sds_len_set(str, len); + } else { + cfl_sds_len_set(str, len); + } + + if (!strchr(str, '.')) { + cfl_sds_cat_safe(&str, ".0", 2); + } + + return str; +} + +static void format_metric_name(cfl_sds_t *buf, struct cmt_map *map, const char *suffix) +{ + int mlen = 0; + int slen = 0; + cfl_sds_t metric_name = NULL; + struct cmt_opts *opts; + + opts = map->opts; + + if (cfl_sds_len(opts->subsystem) > 0) { + /* Calculate length for "metric_name:subsystem.name": */ + mlen = 13 + cfl_sds_len(opts->subsystem) + 1 + cfl_sds_len(opts->name) + 2; + metric_name = cfl_sds_create_size(mlen); + cfl_sds_cat_safe(&metric_name, "\"metric_name:", 13); + cfl_sds_cat_safe(&metric_name, opts->subsystem, cfl_sds_len(opts->subsystem)); + cfl_sds_cat_safe(&metric_name, ".", 1); + cfl_sds_cat_safe(&metric_name, opts->name, cfl_sds_len(opts->name)); + } + else { + /* Calculate length for "metric_name:subsystem.name": */ + mlen = 13 + cfl_sds_len(opts->name) + 2; + metric_name = cfl_sds_create_size(mlen); + cfl_sds_cat_safe(&metric_name, "\"metric_name:", 13); + cfl_sds_cat_safe(&metric_name, opts->name, cfl_sds_len(opts->name)); + } + if (suffix != NULL) { + slen = strlen(suffix); + mlen += slen; + cfl_sds_cat_safe(&metric_name, suffix, slen); + } + cfl_sds_cat_safe(&metric_name, "\":", 2); + cfl_sds_cat_safe(buf, metric_name, mlen); + cfl_sds_destroy(metric_name); +} + +static void format_metric_type(cfl_sds_t *buf, const char *metric_type_name) +{ + int len = 0; + char tmp[32]; + + len = snprintf(tmp, sizeof(tmp) - 1, ",\"metric_type\":\"%s\"", metric_type_name); + cfl_sds_cat_safe(buf, tmp, len); +} + +static void append_metric_value(cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int len; + double val; + char tmp[128]; + cfl_sds_t metric_val; + + /* Retreive metric name */ + format_metric_name(buf, map, NULL); + + /* Retrieve metric value */ + val = cmt_metric_get_value(metric); + metric_val = double_to_string(val); + + len = snprintf(tmp, sizeof(tmp) - 1, "%s", metric_val); + cfl_sds_cat_safe(buf, tmp, len); + cfl_sds_destroy(metric_val); +} + +static void format_context_common(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int len, tlen; + char hostname[256], timestamp[128]; + char *index = NULL, *source = NULL, *source_type = NULL; + struct timespec tms; + uint64_t ts; + int result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; + + /* Open parenthesis */ + cfl_sds_cat_safe(buf, "{", 1); + + /* host */ + len = snprintf(hostname, sizeof(hostname) - 1, "\"host\":\"%s\",", context->host); + cfl_sds_cat_safe(buf, hostname, len); + + /* timestamp (RFC3339Nano) */ + ts = cmt_metric_get_timestamp(metric); + cmt_time_from_ns(&tms, ts); + + /* timestamp (floting point) */ + len = snprintf(timestamp, sizeof(timestamp) - 1, "\"time\":%09lu.%09lu,", tms.tv_sec, tms.tv_nsec); + cfl_sds_cat_safe(buf, timestamp, len); + + /* event type: metric */ + cfl_sds_cat_safe(buf, "\"event\":\"metric\",", 17); + + /* index */ + if (context->index != NULL) { + tlen = strlen(context->index) + 12; /* adding snprintf template character length */ + index = malloc(tlen); + if (index == NULL) { + cmt_errno(); + result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; + + goto cleanup; + } + len = snprintf(index, tlen, "\"index\":\"%s\",", context->index); + cfl_sds_cat_safe(buf, index, len); + free(index); + } + + /* source */ + if (context->source != NULL) { + tlen = strlen(context->source) + 13; /* adding snprintf template character length */ + source = malloc(tlen); + if (source == NULL) { + cmt_errno(); + result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; + + goto cleanup; + } + len = snprintf(source, tlen, "\"source\":\"%s\",", context->source); + cfl_sds_cat_safe(buf, source, len); + free(source); + } + + /* sourcetype */ + if (context->source_type != NULL) { + tlen = strlen(context->source_type) + 18; /* adding snprintf template character length */ + source_type = malloc(tlen); + if (source == NULL) { + cmt_errno(); + result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; + + goto cleanup; + } + len = snprintf(source_type, tlen, "\"sourcetype\":\"%s\",", context->source_type); + cfl_sds_cat_safe(buf, source_type, len); + free(source_type); + } + + return; + +cleanup: + if (result != CMT_ENCODE_SPLUNK_HEC_SUCCESS) { + if (index != NULL) { + free(index); + } + if (source != NULL) { + free(source); + } + if (source_type != NULL) { + free(source_type); + } + } +} + +static void format_metric_labels(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int i; + int n; + int count = 0; + int static_labels = 0; + + struct cmt_map_label *label_k; + struct cmt_map_label *label_v; + struct cfl_list *head; + struct cmt_label *slabel; + + /* Static labels */ + static_labels = cmt_labels_count(context->cmt->static_labels); + if (static_labels > 0) { + cfl_sds_cat_safe(buf, ",", 1); + cfl_list_foreach(head, &context->cmt->static_labels->list) { + count++; + cfl_sds_cat_safe(buf, "\"", 1); + slabel = cfl_list_entry(head, struct cmt_label, _head); + cfl_sds_cat_safe(buf, slabel->key, cfl_sds_len(slabel->key)); + cfl_sds_cat_safe(buf, "\":\"", 3); + cfl_sds_cat_safe(buf, slabel->val, cfl_sds_len(slabel->val)); + cfl_sds_cat_safe(buf, "\"", 1); + + if (count < static_labels) { + cfl_sds_cat_safe(buf, ",", 1); + } + } + } + + n = cfl_list_size(&metric->labels); + if (n > 0) { + cfl_sds_cat_safe(buf, ",", 1); + label_k = cfl_list_entry_first(&map->label_keys, struct cmt_map_label, _head); + + i = 0; + cfl_list_foreach(head, &metric->labels) { + label_v = cfl_list_entry(head, struct cmt_map_label, _head); + + cfl_sds_cat_safe(buf, "\"", 1); + cfl_sds_cat_safe(buf, label_k->name, cfl_sds_len(label_k->name)); + cfl_sds_cat_safe(buf, "\":\"", 3); + cfl_sds_cat_safe(buf, label_v->name, cfl_sds_len(label_v->name)); + cfl_sds_cat_safe(buf, "\"", 1); + i++; + + label_k = cfl_list_entry_next(&label_k->_head, struct cmt_map_label, + _head, &map->label_keys); + if (i < n) { + cfl_sds_cat_safe(buf, ",", 1); + } + } + } +} + +static void append_bucket_metric(cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric, int index) +{ + int len = 0; + double val; + char tmp[128]; + cfl_sds_t metric_val; + + /* metric name for bucket */ + format_metric_name(buf, map, "_bucket"); + + /* Retrieve metric value */ + val = cmt_metric_hist_get_value(metric, index); + metric_val = double_to_string(val); + + len = snprintf(tmp, sizeof(tmp) - 1, "%s", metric_val); + cfl_sds_cat_safe(buf, tmp, len); + cfl_sds_destroy(metric_val); +} + +static void format_histogram_bucket(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int index; + int len = 0; + char tmp[128]; + cfl_sds_t val; + uint64_t metric_val; + struct cmt_histogram *histogram; + struct cmt_histogram_buckets *buckets; + cfl_sds_t metric_str; + + histogram = (struct cmt_histogram *) map->parent; + buckets = histogram->buckets; + + for (index = 0; index <= buckets->count; index++) { + /* Common fields */ + format_context_common(context, buf, map, metric); + + /* Other fields */ + cfl_sds_cat_safe(buf, "\"fields\":{", 10); + + /* bucket metric */ + append_bucket_metric(buf, map, metric, index); + + /* upper bound */ + cfl_sds_cat_safe(buf, ",\"le\":", 6); + + if (index < buckets->count) { + cfl_sds_cat_safe(buf, "\"", 1); + val = double_to_string(buckets->upper_bounds[index]); + cfl_sds_cat_safe(buf, val, cfl_sds_len(val)); + cfl_sds_destroy(val); + cfl_sds_cat_safe(buf, "\"", 1); + } + else { + cfl_sds_cat_safe(buf, "\"+Inf\"", 6); + } + + /* Format labels */ + format_metric_labels(context, buf, map, metric); + + /* Format metric type */ + format_metric_type(buf, "Histogram"); + + /* Close parenthesis for fields */ + cfl_sds_cat_safe(buf, "}", 1); + + /* Close parenthesis */ + cfl_sds_cat_safe(buf, "}", 1); + } + + /* Format histogram sum */ + { + /* Common fields */ + format_context_common(context, buf, map, metric); + + /* Other fields */ + cfl_sds_cat_safe(buf, "\"fields\":{", 10); + + /* metric name for bucket */ + format_metric_name(buf, map, "_sum"); + + /* Retrieve metric value */ + metric_val = cmt_metric_hist_get_sum_value(metric); + metric_str = double_to_string(metric_val); + + len = snprintf(tmp, sizeof(tmp) - 1, "%s", metric_str); + cfl_sds_cat_safe(buf, tmp, len); + cfl_sds_destroy(metric_str); + + /* Format labels */ + format_metric_labels(context, buf, map, metric); + + /* Format metric type */ + format_metric_type(buf, "Histogram"); + + /* Close parenthesis for fields */ + cfl_sds_cat_safe(buf, "}", 1); + + /* Close parenthesis */ + cfl_sds_cat_safe(buf, "}", 1); + } + + /* Format histogram sum */ + { + /* Common fields */ + format_context_common(context, buf, map, metric); + + /* Other fields */ + cfl_sds_cat_safe(buf, "\"fields\":{", 10); + + /* metric name for bucket */ + format_metric_name(buf, map, "_count"); + + /* Retrieve metric value */ + metric_val = cmt_metric_hist_get_count_value(metric); + metric_str = double_to_string(metric_val); + + len = snprintf(tmp, sizeof(tmp) - 1, "%s", metric_str); + cfl_sds_cat_safe(buf, tmp, len); + cfl_sds_destroy(metric_str); + + /* Format labels */ + format_metric_labels(context, buf, map, metric); + + /* Format metric type */ + format_metric_type(buf, "Histogram"); + + /* Close parenthesis for fields */ + cfl_sds_cat_safe(buf, "}", 1); + + /* Close parenthesis */ + cfl_sds_cat_safe(buf, "}", 1); + } +} + +static void append_quantiles_metric(cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric, int index) +{ + int len = 0; + double val; + char tmp[128]; + cfl_sds_t metric_val; + + /* metric name for bucket */ + format_metric_name(buf, map, NULL); + + /* Retrieve metric value */ + val = cmt_summary_quantile_get_value(metric, index); + metric_val = double_to_string(val); + + len = snprintf(tmp, sizeof(tmp) - 1, "%s", metric_val); + cfl_sds_cat_safe(buf, tmp, len); + cfl_sds_destroy(metric_val); +} + +static void format_summary_metric(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int index; + int len = 0; + char tmp[128]; + cfl_sds_t val; + uint64_t metric_val; + struct cmt_summary *summary; + cfl_sds_t metric_str; + + summary = (struct cmt_summary *) map->parent; + + if (metric->sum_quantiles_set) { + for (index = 0; index < summary->quantiles_count; index++) { + /* Common fields */ + format_context_common(context, buf, map, metric); + + /* Other fields */ + cfl_sds_cat_safe(buf, "\"fields\":{", 10); + + /* bucket metric */ + append_quantiles_metric(buf, map, metric, index); + + /* quantiles */ + cfl_sds_cat_safe(buf, ",\"qt\":\"", 7); + val = double_to_string(summary->quantiles[index]); + cfl_sds_cat_safe(buf, val, cfl_sds_len(val)); + cfl_sds_destroy(val); + cfl_sds_cat_safe(buf, "\"", 1); + + /* Format labels */ + format_metric_labels(context, buf, map, metric); + + /* Format metric type */ + format_metric_type(buf, "Summary"); + + /* Close parenthesis for fields */ + cfl_sds_cat_safe(buf, "}", 1); + + /* Close parenthesis */ + cfl_sds_cat_safe(buf, "}", 1); + } + } + + /* Format Summary sum */ + { + /* Common fields */ + format_context_common(context, buf, map, metric); + + /* Other fields */ + cfl_sds_cat_safe(buf, "\"fields\":{", 10); + + /* metric name for bucket */ + format_metric_name(buf, map, "_sum"); + + /* Retrieve metric value */ + metric_val = cmt_summary_get_sum_value(metric); + metric_str = double_to_string(metric_val); + + len = snprintf(tmp, sizeof(tmp) - 1, "%s", metric_str); + cfl_sds_cat_safe(buf, tmp, len); + cfl_sds_destroy(metric_str); + + /* Format labels */ + format_metric_labels(context, buf, map, metric); + + /* Format metric type */ + format_metric_type(buf, "Summary"); + + /* Close parenthesis for fields */ + cfl_sds_cat_safe(buf, "}", 1); + + /* Close parenthesis */ + cfl_sds_cat_safe(buf, "}", 1); + } + + /* Format summary count */ + { + /* Common fields */ + format_context_common(context, buf, map, metric); + + /* Other fields */ + cfl_sds_cat_safe(buf, "\"fields\":{", 10); + + /* metric name for bucket */ + format_metric_name(buf, map, "_count"); + + /* Retrieve metric value */ + metric_val = cmt_summary_get_count_value(metric); + metric_str = double_to_string(metric_val); + + len = snprintf(tmp, sizeof(tmp) - 1, "%s", metric_str); + cfl_sds_cat_safe(buf, tmp, len); + cfl_sds_destroy(metric_str); + + /* Format labels */ + format_metric_labels(context, buf, map, metric); + + /* Format metric type */ + format_metric_type(buf, "Summary"); + + /* Close parenthesis for fields */ + cfl_sds_cat_safe(buf, "}", 1); + + /* Close parenthesis */ + cfl_sds_cat_safe(buf, "}", 1); + } +} + +static void format_metric_data_points(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + /* Common fields */ + format_context_common(context, buf, map, metric); + + /* Other fields */ + cfl_sds_cat_safe(buf, "\"fields\":{", 10); + + /* Metric name and value */ + append_metric_value(buf, map, metric); + + /* Format labels */ + format_metric_labels(context, buf, map, metric); + + /* Close parenthesis for fields */ + cfl_sds_cat_safe(buf, "}", 1); + + /* Close parenthesis */ + cfl_sds_cat_safe(buf, "}", 1); +} + +static void format_metric(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + if (map->type == CMT_HISTOGRAM) { + return format_histogram_bucket(context, buf, map, metric); + } + else if (map->type == CMT_SUMMARY) { + return format_summary_metric(context, buf, map, metric); + } + else { + /* For Counter, Gauge, and Untyped types */ + return format_metric_data_points(context, buf, map, metric); + } +} + +static void format_metrics(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map) +{ + struct cfl_list *head; + struct cmt_metric *metric; + + /* Simple metric, no labels */ + if (map->metric_static_set == 1) { + format_metric(context, buf, map, &map->metric); + } + + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + format_metric(context, buf, map, metric); + } +} + +static void destroy_splunk_hec_context(struct cmt_splunk_hec_context *context) +{ + if (context != NULL) { + free(context); + } +} + +static struct cmt_splunk_hec_context +*initialize_splunk_hec_context(struct cmt *cmt, const char *host, + const char *index, const char *source, const char *source_type) +{ + int result = CMT_ENCODE_SPLUNK_HEC_SUCCESS; + struct cmt_splunk_hec_context *context = NULL; + + context = calloc(1, sizeof(struct cmt_splunk_hec_context)); + if (context == NULL) { + result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; + + goto cleanup; + } + + /* host parameter is mandatory. */ + if (host == NULL) { + result = CMT_ENCODE_SPLUNK_HEC_INVALID_ARGUMENT_ERROR; + + goto cleanup; + } + + memset(context, 0, sizeof(struct cmt_splunk_hec_context)); + context->cmt = cmt; + context->host = host; + context->index = NULL; + context->source = NULL; + context->source_type = NULL; + + /* Setting up optional members. */ + if (index != NULL) { + context->index = index; + } + if (source != NULL) { + context->source = source; + } + if (source_type != NULL) { + context->source_type = source_type; + } + +cleanup: + if (result != CMT_ENCODE_SPLUNK_HEC_SUCCESS) { + if (context != NULL) { + destroy_splunk_hec_context(context); + + context = NULL; + } + } + + return context; +} + +/* Format all the registered metrics in Splunk HEC JSON format */ +cfl_sds_t cmt_encode_splunk_hec_create(struct cmt *cmt, const char *host, + const char *index, const char *source, const char *source_type) +{ + cfl_sds_t buf; + struct cfl_list *head; + struct cmt_counter *counter; + struct cmt_gauge *gauge; + struct cmt_untyped *untyped; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + struct cmt_splunk_hec_context *context; + + context = initialize_splunk_hec_context(cmt, host, index, source, source_type); + + if (context == NULL) { + return NULL; + } + + /* Allocate a 1KB of buffer */ + buf = cfl_sds_create_size(1024); + if (!buf) { + return NULL; + } + + /* Counters */ + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + format_metrics(context, &buf, counter->map); + } + + /* Gauges */ + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + format_metrics(context, &buf, gauge->map); + } + + /* Summaries */ + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + format_metrics(context, &buf, summary->map); + } + + /* Histograms */ + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + format_metrics(context, &buf, histogram->map); + } + + /* Untyped */ + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + format_metrics(context, &buf, untyped->map); + } + + if (context != NULL) { + destroy_splunk_hec_context(context); + } + + return buf; +} + +void cmt_encode_splunk_hec_destroy(cfl_sds_t text) +{ + cfl_sds_destroy(text); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_encode_text.c b/fluent-bit/lib/cmetrics/src/cmt_encode_text.c new file mode 100644 index 00000000..ffdfe314 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_encode_text.c @@ -0,0 +1,332 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_counter.h> +#include <cmetrics/cmt_gauge.h> +#include <cmetrics/cmt_untyped.h> +#include <cmetrics/cmt_histogram.h> +#include <cmetrics/cmt_summary.h> +#include <cmetrics/cmt_time.h> +#include <cmetrics/cmt_compat.h> + +static void append_histogram_metric_value(cfl_sds_t *buf, + struct cmt_map *map, + struct cmt_metric *metric) +{ + char *bucket_value_format_string; + size_t entry_buffer_length; + size_t entry_buffer_index; + char entry_buffer[256]; + struct cmt_histogram *histogram; + struct cmt_histogram_buckets *buckets; + size_t index; + + histogram = (struct cmt_histogram *) map->parent; + buckets = histogram->buckets; + + cfl_sds_cat_safe(buf, " = { buckets = { ", 17); + + for (index = 0 ; index <= buckets->count ; index++) { + if (index < buckets->count) { + entry_buffer_index = snprintf(entry_buffer, + sizeof(entry_buffer) - 1, + "%g", + buckets->upper_bounds[index]); + + bucket_value_format_string = "=%" PRIu64 ", "; + } + else { + entry_buffer_index = snprintf(entry_buffer, + sizeof(entry_buffer) - 1, + "+Inf"); + + bucket_value_format_string = "=%" PRIu64 " "; + } + + entry_buffer_length = entry_buffer_index; + + entry_buffer_length += snprintf(&entry_buffer[entry_buffer_index], + sizeof(entry_buffer) - 1 - + entry_buffer_index, + bucket_value_format_string, + cmt_metric_hist_get_value(metric, + index)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + } + + cfl_sds_cat_safe(buf, "}, ", 3); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "sum=%g, ", + cmt_metric_hist_get_sum_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "count=%" PRIu64 , + cmt_metric_hist_get_count_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + cfl_sds_cat_safe(buf, " }\n", 3); +} + +static void append_summary_metric_value(cfl_sds_t *buf, + struct cmt_map *map, + struct cmt_metric *metric) +{ + char *quantile_pair_format_string; + size_t entry_buffer_length; + char entry_buffer[256]; + struct cmt_summary *summary; + size_t index; + + summary = (struct cmt_summary *) map->parent; + + cfl_sds_cat_safe(buf, " = { quantiles = { ", 19); + + for (index = 0 ; index < summary->quantiles_count ; index++) { + if (index < summary->quantiles_count - 1) { + quantile_pair_format_string = "%g=%g, "; + } + else { + quantile_pair_format_string = "%g=%g "; + } + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1, + quantile_pair_format_string, + summary->quantiles[index], + cmt_summary_quantile_get_value(metric, + index)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + } + + cfl_sds_cat_safe(buf, "}, ", 3); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "sum=%g, ", + cmt_summary_get_sum_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + entry_buffer_length = snprintf(entry_buffer, + sizeof(entry_buffer) - 1 , + "count=%" PRIu64, + cmt_summary_get_count_value(metric)); + + cfl_sds_cat_safe(buf, entry_buffer, entry_buffer_length); + + cfl_sds_cat_safe(buf, " }\n", 3); +} + +static void append_metric_value(cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int len; + double val; + char tmp[128]; + + if (map->type == CMT_HISTOGRAM) { + return append_histogram_metric_value(buf, map, metric); + } + else if (map->type == CMT_SUMMARY) { + return append_summary_metric_value(buf, map, metric); + } + + /* Retrieve metric value */ + val = cmt_metric_get_value(metric); + + len = snprintf(tmp, sizeof(tmp) - 1, " = %.17g\n", val); + cfl_sds_cat_safe(buf, tmp, len); +} + +static void format_metric(struct cmt *cmt, cfl_sds_t *buf, struct cmt_map *map, + struct cmt_metric *metric) +{ + int i; + int n; + int len; + int count = 0; + int static_labels = 0; + char tmp[128]; + uint64_t ts; + struct tm tm; + struct timespec tms; + struct cmt_map_label *label_k; + struct cmt_map_label *label_v; + struct cfl_list *head; + struct cmt_opts *opts; + struct cmt_label *slabel; + + opts = map->opts; + + /* timestamp (RFC3339Nano) */ + ts = cmt_metric_get_timestamp(metric); + + cmt_time_from_ns(&tms, ts); + + cmt_platform_gmtime_r(&tms.tv_sec, &tm); + len = strftime(tmp, sizeof(tmp) - 1, "%Y-%m-%dT%H:%M:%S.", &tm); + cfl_sds_cat_safe(buf, tmp, len); + + len = snprintf(tmp, sizeof(tmp) - 1, "%09luZ ", tms.tv_nsec); + cfl_sds_cat_safe(buf, tmp, len); + + /* Metric info */ + cfl_sds_cat_safe(buf, opts->fqname, cfl_sds_len(opts->fqname)); + + /* Static labels */ + static_labels = cmt_labels_count(cmt->static_labels); + if (static_labels > 0) { + cfl_sds_cat_safe(buf, "{", 1); + cfl_list_foreach(head, &cmt->static_labels->list) { + count++; + slabel = cfl_list_entry(head, struct cmt_label, _head); + cfl_sds_cat_safe(buf, slabel->key, cfl_sds_len(slabel->key)); + cfl_sds_cat_safe(buf, "=\"", 2); + cfl_sds_cat_safe(buf, slabel->val, cfl_sds_len(slabel->val)); + cfl_sds_cat_safe(buf, "\"", 1); + + if (count < static_labels) { + cfl_sds_cat_safe(buf, ",", 1); + } + } + } + + n = cfl_list_size(&metric->labels); + if (n > 0) { + if (static_labels > 0) { + cfl_sds_cat_safe(buf, ",", 1); + } + else { + cfl_sds_cat_safe(buf, "{", 1); + } + + label_k = cfl_list_entry_first(&map->label_keys, struct cmt_map_label, _head); + + i = 1; + cfl_list_foreach(head, &metric->labels) { + label_v = cfl_list_entry(head, struct cmt_map_label, _head); + + cfl_sds_cat_safe(buf, label_k->name, cfl_sds_len(label_k->name)); + cfl_sds_cat_safe(buf, "=\"", 2); + cfl_sds_cat_safe(buf, label_v->name, cfl_sds_len(label_v->name)); + + if (i < n) { + cfl_sds_cat_safe(buf, "\",", 2); + } + else { + cfl_sds_cat_safe(buf, "\"", 1); + } + i++; + + label_k = cfl_list_entry_next(&label_k->_head, struct cmt_map_label, + _head, &map->label_keys); + } + cfl_sds_cat_safe(buf, "}", 1); + + append_metric_value(buf, map, metric); + } + else { + if (static_labels > 0) { + cfl_sds_cat_safe(buf, "}", 1); + } + append_metric_value(buf, map, metric); + } +} + +static void format_metrics(struct cmt *cmt, cfl_sds_t *buf, struct cmt_map *map) +{ + struct cfl_list *head; + struct cmt_metric *metric; + + /* Simple metric, no labels */ + if (map->metric_static_set == 1) { + format_metric(cmt, buf, map, &map->metric); + } + + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + format_metric(cmt, buf, map, metric); + } +} + +/* Format all the registered metrics in Prometheus Text format */ +cfl_sds_t cmt_encode_text_create(struct cmt *cmt) +{ + cfl_sds_t buf; + struct cfl_list *head; + struct cmt_counter *counter; + struct cmt_gauge *gauge; + struct cmt_untyped *untyped; + struct cmt_summary *summary; + struct cmt_histogram *histogram; + + /* Allocate a 1KB of buffer */ + buf = cfl_sds_create_size(1024); + if (!buf) { + return NULL; + } + + /* Counters */ + cfl_list_foreach(head, &cmt->counters) { + counter = cfl_list_entry(head, struct cmt_counter, _head); + format_metrics(cmt, &buf, counter->map); + } + + /* Gauges */ + cfl_list_foreach(head, &cmt->gauges) { + gauge = cfl_list_entry(head, struct cmt_gauge, _head); + format_metrics(cmt, &buf, gauge->map); + } + + /* Summaries */ + cfl_list_foreach(head, &cmt->summaries) { + summary = cfl_list_entry(head, struct cmt_summary, _head); + format_metrics(cmt, &buf, summary->map); + } + + /* Histograms */ + cfl_list_foreach(head, &cmt->histograms) { + histogram = cfl_list_entry(head, struct cmt_histogram, _head); + format_metrics(cmt, &buf, histogram->map); + } + + /* Untyped */ + cfl_list_foreach(head, &cmt->untypeds) { + untyped = cfl_list_entry(head, struct cmt_untyped, _head); + format_metrics(cmt, &buf, untyped->map); + } + + return buf; +} + +void cmt_encode_text_destroy(cfl_sds_t text) +{ + cfl_sds_destroy(text); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_gauge.c b/fluent-bit/lib/cmetrics/src/cmt_gauge.c new file mode 100644 index 00000000..16c8f48b --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_gauge.c @@ -0,0 +1,198 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_math.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_gauge.h> + +struct cmt_gauge *cmt_gauge_create(struct cmt *cmt, + char *ns, char *subsystem, char *name, + char *help, int label_count, char **label_keys) +{ + int ret; + struct cmt_gauge *gauge; + + if (!ns) { + cmt_log_error(cmt, "null ns not allowed"); + return NULL; + } + + if (!subsystem) { + cmt_log_error(cmt, "null subsystem not allowed"); + return NULL; + } + + if (!name || strlen(name) == 0) { + cmt_log_error(cmt, "undefined name"); + return NULL; + } + + if (!help || strlen(help) == 0) { + cmt_log_error(cmt, "undefined help"); + return NULL; + } + + gauge = calloc(1, sizeof(struct cmt_gauge)); + if (!gauge) { + cmt_errno(); + return NULL; + } + cfl_list_add(&gauge->_head, &cmt->gauges); + + /* Initialize options */ + ret = cmt_opts_init(&gauge->opts, ns, subsystem, name, help); + if (ret == -1) { + cmt_log_error(cmt, "unable to initialize options for gauge"); + cmt_gauge_destroy(gauge); + return NULL; + } + + /* Create the map */ + gauge->map = cmt_map_create(CMT_GAUGE, &gauge->opts, label_count, label_keys, + (void *) gauge); + if (!gauge->map) { + cmt_log_error(cmt, "unable to allocate map for gauge"); + cmt_gauge_destroy(gauge); + return NULL; + } + + gauge->cmt = cmt; + + return gauge; +} + +int cmt_gauge_destroy(struct cmt_gauge *gauge) +{ + cfl_list_del(&gauge->_head); + cmt_opts_exit(&gauge->opts); + if (gauge->map) { + cmt_map_destroy(gauge->map); + } + free(gauge); + return 0; +} + +int cmt_gauge_set(struct cmt_gauge *gauge, uint64_t timestamp, double val, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&gauge->opts, gauge->map, labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(gauge->cmt, "unable to retrieve metric: %s for gauge %s_%s_%s", + gauge->map, gauge->opts.ns, gauge->opts.subsystem, + gauge->opts.name); + return -1; + } + cmt_metric_set(metric, timestamp, val); + return 0; +} + +int cmt_gauge_inc(struct cmt_gauge *gauge, uint64_t timestamp, + int labels_count, char **label_vals) + +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&gauge->opts, gauge->map, labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(gauge->cmt, "unable to retrieve metric: %s for gauge %s_%s_%s", + gauge->map, gauge->opts.ns, gauge->opts.subsystem, + gauge->opts.name); + return -1; + } + cmt_metric_inc(metric, timestamp); + return 0; +} + +int cmt_gauge_dec(struct cmt_gauge *gauge, uint64_t timestamp, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&gauge->opts, gauge->map, labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(gauge->cmt, "unable to retrieve metric: %s for gauge %s_%s_%s", + gauge->map, gauge->opts.ns, gauge->opts.subsystem, + gauge->opts.name); + return -1; + } + cmt_metric_dec(metric, timestamp); + return 0; +} + +int cmt_gauge_add(struct cmt_gauge *gauge, uint64_t timestamp, double val, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&gauge->opts, gauge->map, labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(gauge->cmt, "unable to retrieve metric: %s for gauge %s_%s_%s", + gauge->map, gauge->opts.ns, gauge->opts.subsystem, + gauge->opts.name); + return -1; + } + cmt_metric_add(metric, timestamp, val); + return 0; +} + +int cmt_gauge_sub(struct cmt_gauge *gauge, uint64_t timestamp, double val, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&gauge->opts, gauge->map, labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(gauge->cmt, "unable to retrieve metric: %s for gauge %s_%s_%s", + gauge->map, gauge->opts.ns, gauge->opts.subsystem, + gauge->opts.name); + return -1; + } + cmt_metric_sub(metric, timestamp, val); + return 0; +} + +int cmt_gauge_get_val(struct cmt_gauge *gauge, + int labels_count, char **label_vals, double *out_val) +{ + int ret; + double val = 0; + + ret = cmt_map_metric_get_val(&gauge->opts, + gauge->map, labels_count, label_vals, + &val); + if (ret == -1) { + cmt_log_error(gauge->cmt, + "unable to retrieve metric value: %s for gauge %s_%s_%s", + gauge->map, gauge->opts.ns, gauge->opts.subsystem, + gauge->opts.name); + return -1; + } + *out_val = val; + return 0; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_histogram.c b/fluent-bit/lib/cmetrics/src/cmt_histogram.c new file mode 100644 index 00000000..ae895f3a --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_histogram.c @@ -0,0 +1,403 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_histogram.h> + +#include <stdarg.h> + +struct cmt_histogram_buckets *cmt_histogram_buckets_create_size(double *bkts, size_t count) +{ + int i; + double *upper_bounds; + struct cmt_histogram_buckets *buckets; + + if (count < 1) { + return NULL; + } + + /* besides buckets set by the user, we add an implicit bucket for +inf */ + upper_bounds = calloc(1, sizeof(double) * count + 1); + if (!upper_bounds) { + cmt_errno(); + return NULL; + } + + buckets = calloc(1, sizeof(struct cmt_histogram_buckets)); + if (!buckets) { + cmt_errno(); + free(upper_bounds); + return NULL; + } + + buckets->count = count; + buckets->upper_bounds = upper_bounds; + + if (bkts != NULL) { + for (i = 0; i < count; i++) { + upper_bounds[i] = bkts[i]; + } + } + + return buckets; +} + +struct cmt_histogram_buckets *cmt_histogram_buckets_create(size_t count, ...) +{ + int i; + double *bucket_array; + struct cmt_histogram_buckets *buckets; + va_list va; + + bucket_array = calloc(count, sizeof(double)); + if (!bucket_array) { + return NULL; + } + + va_start(va, count); + for (i = 0; i < count; i++) { + bucket_array[i] = va_arg(va, double); + } + va_end(va); + + buckets = cmt_histogram_buckets_create_size(bucket_array, count); + free(bucket_array); + + return buckets; +} + +/* Create default buckets */ +struct cmt_histogram_buckets *cmt_histogram_buckets_default_create() +{ + return cmt_histogram_buckets_create_size((double[]) { + 0.005, 0.01, 0.025, 0.05, + 0.1, 0.25, 0.5, 1.0, 2.5, + 5.0, 10.0 }, 11); +} + +/* Linear bucket creation */ +struct cmt_histogram_buckets *cmt_histogram_buckets_linear_create(double start, + double width, + size_t count) +{ + int i; + double *upper_bounds; + struct cmt_histogram_buckets *buckets; + + if (count <= 1) { + return NULL; + } + + upper_bounds = calloc(1, sizeof(double) * count); + if (!upper_bounds) { + cmt_errno(); + return NULL; + } + + buckets = calloc(1, sizeof(struct cmt_histogram_buckets)); + if (!buckets) { + cmt_errno(); + free(upper_bounds); + return NULL; + } + + buckets->count = count; + buckets->upper_bounds = upper_bounds; + + /* initialize first bucket */ + upper_bounds[0] = start; + + for (i = 1; i < count; i++) { + upper_bounds[i] = upper_bounds[i - 1] + width; + } + + return buckets; +} + +/* Exponential bucket creation */ +struct cmt_histogram_buckets *cmt_histogram_buckets_exponential_create(double start, + double factor, + size_t count) +{ + int i; + double *upper_bounds; + struct cmt_histogram_buckets *buckets; + + if (start <= 0) { + return NULL; + } + + if (factor <= 1) { + return NULL; + } + + if (count < 1) { + return NULL; + } + + upper_bounds = calloc(1, sizeof(double) * count); + if (!upper_bounds) { + cmt_errno(); + return NULL; + } + + buckets = calloc(1, sizeof(struct cmt_histogram_buckets)); + if (!buckets) { + cmt_errno(); + free(upper_bounds); + return NULL; + } + + buckets->count = count; + buckets->upper_bounds = upper_bounds; + + /* initialize first bucket */ + upper_bounds[0] = start; + + for (i = 1; i < count; i++) { + upper_bounds[i] = upper_bounds[i - 1] * factor; + } + + return buckets; +} + +void cmt_histogram_buckets_destroy(struct cmt_histogram_buckets *buckets) +{ + if (!buckets) { + return; + } + + if (buckets->upper_bounds) { + free(buckets->upper_bounds); + } + + free(buckets); +} + +static int check_buckets(struct cmt_histogram_buckets *buckets) +{ + int i; + + for (i = 1; i < buckets->count; i++) { + if (buckets->upper_bounds[i - 1] > buckets->upper_bounds[i]) { + return -1; + } + } + + return 0; +} + +struct cmt_histogram *cmt_histogram_create(struct cmt *cmt, + char *ns, char *subsystem, + char *name, char *help, + struct cmt_histogram_buckets *buckets, + int label_count, char **label_keys) +{ + int ret; + struct cmt_histogram *h; + + if (!ns) { + cmt_log_error(cmt, "null ns not allowed"); + return NULL; + } + + if (!subsystem) { + cmt_log_error(cmt, "null subsystem not allowed"); + return NULL; + } + + if (!name || strlen(name) == 0) { + cmt_log_error(cmt, "undefined name"); + return NULL; + } + + if (!help || strlen(help) == 0) { + cmt_log_error(cmt, "undefined help"); + return NULL; + } + + h = calloc(1, sizeof(struct cmt_histogram)); + if (!h) { + cmt_errno(); + return NULL; + } + cfl_list_add(&h->_head, &cmt->histograms); + + /* set buckets */ + if (buckets) { + h->buckets = buckets; + } + else { + /* set 'default' buckets */ + h->buckets = cmt_histogram_buckets_default_create(); + if (!h->buckets) { + cmt_histogram_destroy(h); + return NULL; + } + } + + /* Validate buckets order */ + ret = check_buckets(h->buckets); + if (ret != 0) { + cmt_histogram_destroy(h); + return NULL; + } + + /* initialize options */ + ret = cmt_opts_init(&h->opts, ns, subsystem, name, help); + if (ret == -1) { + cmt_log_error(cmt, "unable to initialize options for histogram"); + cmt_histogram_destroy(h); + return NULL; + } + + /* Create the map */ + h->map = cmt_map_create(CMT_HISTOGRAM, &h->opts, label_count, label_keys, + (void *) h); + if (!h->map) { + cmt_log_error(cmt, "unable to allocate map for histogram"); + cmt_histogram_destroy(h); + return NULL; + } + + return h; +} + +int cmt_histogram_destroy(struct cmt_histogram *h) +{ + cfl_list_del(&h->_head); + cmt_opts_exit(&h->opts); + + if (h->buckets) { + cmt_histogram_buckets_destroy(h->buckets); + } + + if (h->map) { + cmt_map_destroy(h->map); + } + + free(h); + return 0; +} + +static struct cmt_metric *histogram_get_metric(struct cmt_histogram *histogram, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + struct cmt_histogram_buckets *buckets; + + metric = cmt_map_metric_get(&histogram->opts, histogram->map, + labels_count, label_vals, CMT_TRUE); + if (!metric) { + cmt_log_error(histogram->cmt, + "unable to retrieve metric: %s for histogram %s_%s_%s", + histogram->map, histogram->opts.ns, histogram->opts.subsystem, + histogram->opts.name); + return NULL; + } + + /* ref buckets */ + buckets = histogram->buckets; + + /* make sure buckets has been initialized */ + if (!metric->hist_buckets) { + metric->hist_buckets = calloc(1, sizeof(uint64_t) * (buckets->count + 1)); + if (!metric->hist_buckets) { + cmt_errno(); + return NULL; + } + } + + return metric; +} + +/* Observe the value and put it in the right bucket */ +int cmt_histogram_observe(struct cmt_histogram *histogram, uint64_t timestamp, + double val, int labels_count, char **label_vals) +{ + int i; + struct cmt_metric *metric; + struct cmt_histogram_buckets *buckets; + + metric = histogram_get_metric(histogram, labels_count, label_vals); + if (!metric) { + cmt_log_error(histogram->cmt, + "unable to retrieve metric: %s for histogram %s_%s_%s", + histogram->map, histogram->opts.ns, histogram->opts.subsystem, + histogram->opts.name); + return -1; + } + + /* increment buckets */ + buckets = histogram->buckets; + for (i = buckets->count - 1; i >= 0; i--) { + if (val > buckets->upper_bounds[i]) { + break; + } + cmt_metric_hist_inc(metric, timestamp, i); + } + + /* increment bucket +Inf */ + cmt_metric_hist_inc(metric, timestamp, buckets->count); + + /* increment bucket _count */ + cmt_metric_hist_count_inc(metric, timestamp); + + /* add observed value to _sum */ + cmt_metric_hist_sum_add(metric, timestamp, val); + return 0; +} + +int cmt_histogram_set_default(struct cmt_histogram *histogram, + uint64_t timestamp, + uint64_t *bucket_defaults, + double sum, + uint64_t count, + int labels_count, char **label_vals) +{ + int i; + struct cmt_metric *metric; + struct cmt_histogram_buckets *buckets; + + metric = histogram_get_metric(histogram, labels_count, label_vals); + if (!metric) { + cmt_log_error(histogram->cmt, + "unable to retrieve metric: %s for histogram %s_%s_%s", + histogram->map, histogram->opts.ns, histogram->opts.subsystem, + histogram->opts.name); + return -1; + } + + /* + * For every bucket, set the default value set in 'defaults', note that no + * size check is performed and we trust the caller set the proper array size + */ + buckets = histogram->buckets; + for (i = 0; i <= buckets->count; i++) { + cmt_metric_hist_set(metric, timestamp, i, bucket_defaults[i]); + } + + cmt_metric_hist_sum_set(metric, timestamp, sum); + cmt_metric_hist_count_set(metric, timestamp, count); + + return 0; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_label.c b/fluent-bit/lib/cmetrics/src/cmt_label.c new file mode 100644 index 00000000..911ebb59 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_label.c @@ -0,0 +1,100 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_label.h> + +/* + * This interface file provide helper functions to compose a dynamic list + * of custom labels with specific keys and values. Note that this is not + * about labels defined by metrics upon creation, but label lists to be + * used by the encoders when formatting the data. + */ +struct cmt_labels *cmt_labels_create() +{ + struct cmt_labels *l; + + l = malloc(sizeof(struct cmt_labels)); + if (!l) { + cmt_errno(); + return NULL; + } + cfl_list_init(&l->list); + return l; +} + +void cmt_labels_destroy(struct cmt_labels *labels) +{ + struct cfl_list *tmp; + struct cfl_list *head; + struct cmt_label *l; + + cfl_list_foreach_safe(head, tmp, &labels->list) { + l = cfl_list_entry(head, struct cmt_label, _head); + if (l->key) { + cfl_sds_destroy(l->key); + } + if (l->val) { + cfl_sds_destroy(l->val); + } + cfl_list_del(&l->_head); + free(l); + } + + free(labels); +} + +int cmt_labels_add_kv(struct cmt_labels *labels, char *key, char *val) +{ + struct cmt_label *l; + + l = malloc(sizeof(struct cmt_label)); + if (!l) { + cmt_errno(); + return -1; + } + + l->key = cfl_sds_create(key); + if (!l->key) { + free(l); + return -1; + } + + l->val = cfl_sds_create(val); + if (!l->val) { + cfl_sds_destroy(l->key); + free(l); + return -1; + } + + cfl_list_add(&l->_head, &labels->list); + return 0; +} + +int cmt_labels_count(struct cmt_labels *labels) +{ + int c = 0; + struct cfl_list *head; + + cfl_list_foreach(head, &labels->list) { + c++; + } + + return c; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_log.c b/fluent-bit/lib/cmetrics/src/cmt_log.c new file mode 100644 index 00000000..7711c566 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_log.c @@ -0,0 +1,91 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_compat.h> + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#ifdef _WIN32 + #define strerror_r(errnum, buf, buf_size) strerror_s(buf, buf_size, errnum) +#endif + +void cmt_log_print(void *ctx, int level, const char *file, int line, + const char *fmt, ...) +{ + int ret; + char buf[CMT_LOG_BUF_SIZE]; + va_list args; + struct cmt *cmt = ctx; + + if (!cmt->log_cb) { + return; + } + + if (level > cmt->log_level) { + return; + } + + va_start(args, fmt); + ret = vsnprintf(buf, CMT_LOG_BUF_SIZE - 1, fmt, args); + + if (ret >= 0) { + buf[ret] = '\0'; + } + va_end(args); + + cmt->log_cb(ctx, level, file, line, buf); +} + +int cmt_errno_print(int errnum, const char *file, int line) +{ + char buf[256]; + + strerror_r(errnum, buf, sizeof(buf) - 1); + fprintf(stderr, "[%s:%i errno=%i] %s\n", + file, line, errnum, buf); + return 0; +} + +#ifdef _WIN32 +void cmt_winapi_error_print(const char *func, int line) +{ + int error = GetLastError(); + char buf[256]; + int success; + + success = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error, + LANG_SYSTEM_DEFAULT, + buf, + sizeof(buf), + NULL); + if (success) { + fprintf(stderr, "[%s() line=%i error=%i] %s\n", func, line, error, buf); + } + else { + fprintf(stderr, "[%s() line=%i error=%i] Win32 API failed\n", func, line, error); + } +} +#endif diff --git a/fluent-bit/lib/cmetrics/src/cmt_map.c b/fluent-bit/lib/cmetrics/src/cmt_map.c new file mode 100644 index 00000000..ab25bffb --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_map.c @@ -0,0 +1,318 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_compat.h> + +struct cmt_map *cmt_map_create(int type, struct cmt_opts *opts, int count, char **labels, + void *parent) +{ + int i; + char *name; + struct cmt_map *map; + struct cmt_map_label *label; + + if (count < 0) { + return NULL; + } + + map = calloc(1, sizeof(struct cmt_map)); + if (!map) { + cmt_errno(); + return NULL; + } + map->type = type; + map->opts = opts; + map->parent = parent; + map->label_count = count; + cfl_list_init(&map->label_keys); + cfl_list_init(&map->metrics); + cfl_list_init(&map->metric.labels); + + if (count == 0) { + map->metric_static_set = 1; + } + + for (i = 0; i < count; i++) { + label = malloc(sizeof(struct cmt_map_label)); + if (!label) { + cmt_errno(); + goto error; + } + + name = labels[i]; + label->name = cfl_sds_create(name); + if (!label->name) { + cmt_errno(); + free(label); + goto error; + } + cfl_list_add(&label->_head, &map->label_keys); + } + + return map; + + error: + cmt_map_destroy(map); + return NULL; +} + +static struct cmt_metric *metric_hash_lookup(struct cmt_map *map, uint64_t hash) +{ + struct cfl_list *head; + struct cmt_metric *metric; + + if (hash == 0) { + return &map->metric; + } + + cfl_list_foreach(head, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + if (metric->hash == hash) { + return metric; + } + } + + return NULL; +} + +static struct cmt_metric *map_metric_create(uint64_t hash, + int labels_count, char **labels_val) +{ + int i; + char *name; + struct cmt_metric *metric; + struct cmt_map_label *label; + + metric = calloc(1, sizeof(struct cmt_metric)); + if (!metric) { + cmt_errno(); + return NULL; + } + cfl_list_init(&metric->labels); + metric->val = 0.0; + metric->hash = hash; + + for (i = 0; i < labels_count; i++) { + label = malloc(sizeof(struct cmt_map_label)); + if (!label) { + cmt_errno(); + goto error; + } + + name = labels_val[i]; + label->name = cfl_sds_create(name); + if (!label->name) { + cmt_errno(); + free(label); + goto error; + } + cfl_list_add(&label->_head, &metric->labels); + } + + return metric; + + error: + free(metric); + return NULL; +} + +static void map_metric_destroy(struct cmt_metric *metric) +{ + struct cfl_list *tmp; + struct cfl_list *head; + struct cmt_map_label *label; + + cfl_list_foreach_safe(head, tmp, &metric->labels) { + label = cfl_list_entry(head, struct cmt_map_label, _head); + cfl_sds_destroy(label->name); + cfl_list_del(&label->_head); + free(label); + } + + if (metric->hist_buckets) { + free(metric->hist_buckets); + } + if (metric->sum_quantiles) { + free(metric->sum_quantiles); + } + + cfl_list_del(&metric->_head); + free(metric); +} + +struct cmt_metric *cmt_map_metric_get(struct cmt_opts *opts, struct cmt_map *map, + int labels_count, char **labels_val, + int write_op) +{ + int i; + int len; + char *ptr; + uint64_t hash; + cfl_hash_state_t state; + struct cmt_metric *metric = NULL; + + /* Enforce zero or exact labels */ + if (labels_count > 0 && labels_count != map->label_count) { + return NULL; + } + + /* + * If the caller wants the no-labeled metric (metric_static_set) make sure + * it was already pre-defined. + */ + if (labels_count == 0) { + /* + * if an upcoming 'write operation' will be performed for a default + * static metric, just initialize it and return it. + */ + if (map->metric_static_set) { + metric = &map->metric; + } + else if (write_op) { + metric = &map->metric; + if (!map->metric_static_set) { + map->metric_static_set = 1; + } + } + + /* return the proper context or NULL */ + return metric; + } + + /* Lookup the metric */ + cfl_hash_64bits_reset(&state); + cfl_hash_64bits_update(&state, opts->fqname, cfl_sds_len(opts->fqname)); + for (i = 0; i < labels_count; i++) { + ptr = labels_val[i]; + if (!ptr) { + cfl_hash_64bits_update(&state, "_NULL_", 6); + } + else { + len = strlen(ptr); + cfl_hash_64bits_update(&state, ptr, len); + } + } + + hash = cfl_hash_64bits_digest(&state); + metric = metric_hash_lookup(map, hash); + + if (metric) { + return metric; + } + + /* + * If the metric was not found and the caller will not write a value, just + * return NULL. + */ + if (!write_op) { + return NULL; + } + + /* If the metric has not been found, just create it */ + metric = map_metric_create(hash, labels_count, labels_val); + if (!metric) { + return NULL; + } + cfl_list_add(&metric->_head, &map->metrics); + return metric; +} + +int cmt_map_metric_get_val(struct cmt_opts *opts, struct cmt_map *map, + int labels_count, char **labels_val, + double *out_val) +{ + double val = 0; + struct cmt_metric *metric; + + metric = cmt_map_metric_get(opts, map, labels_count, labels_val, CMT_FALSE); + if (!metric) { + return -1; + } + + val = cmt_metric_get_value(metric); + *out_val = val; + return 0; +} + +void cmt_map_destroy(struct cmt_map *map) +{ + struct cfl_list *tmp; + struct cfl_list *head; + struct cmt_map_label *label; + struct cmt_metric *metric; + + cfl_list_foreach_safe(head, tmp, &map->label_keys) { + label = cfl_list_entry(head, struct cmt_map_label, _head); + cfl_sds_destroy(label->name); + cfl_list_del(&label->_head); + free(label); + } + + cfl_list_foreach_safe(head, tmp, &map->metrics) { + metric = cfl_list_entry(head, struct cmt_metric, _head); + map_metric_destroy(metric); + } + + /* histogram and quantile allocation for static metric */ + if (map->metric_static_set) { + metric = &map->metric; + + if (map->type == CMT_HISTOGRAM) { + if (metric->hist_buckets) { + free(metric->hist_buckets); + } + } + else if (map->type == CMT_SUMMARY) { + if (metric->sum_quantiles) { + free(metric->sum_quantiles); + } + } + } + + free(map); +} + +/* I don't know if we should leave this or promote the label type so it has its own + * header and source files with their own constructor / destructor and an agnostic name. + * That last bit comes from the fact that we are using the cmt_map_label type both in the + * dimension definition list held by the map structure and the dimension value list held + * by the metric structure. + */ + +void destroy_label_list(struct cfl_list *label_list) +{ + struct cfl_list *tmp; + struct cfl_list *head; + struct cmt_map_label *label; + + cfl_list_foreach_safe(head, tmp, label_list) { + label = cfl_list_entry(head, struct cmt_map_label, _head); + + cfl_sds_destroy(label->name); + + cfl_list_del(&label->_head); + + free(label); + } +} + diff --git a/fluent-bit/lib/cmetrics/src/cmt_metric.c b/fluent-bit/lib/cmetrics/src/cmt_metric.c new file mode 100644 index 00000000..dc58d26f --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_metric.c @@ -0,0 +1,142 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_math.h> +#include <cmetrics/cmt_atomic.h> + +static inline int metric_exchange(struct cmt_metric *metric, uint64_t timestamp, + double new_value, double old_value) +{ + uint64_t tmp_new; + uint64_t tmp_old; + int result; + + tmp_new = cmt_math_d64_to_uint64(new_value); + tmp_old = cmt_math_d64_to_uint64(old_value); + + result = cmt_atomic_compare_exchange(&metric->val, tmp_old, tmp_new); + + if(0 == result) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + + return 1; +} + +static inline void add(struct cmt_metric *metric, uint64_t timestamp, double val) +{ + double old; + double new; + int result; + + do { + old = cmt_metric_get_value(metric); + new = old + val; + + result = metric_exchange(metric, timestamp, new, old); + } + while(0 == result); +} + +void cmt_metric_set(struct cmt_metric *metric, uint64_t timestamp, double val) +{ + uint64_t tmp; + + tmp = cmt_math_d64_to_uint64(val); + + cmt_atomic_store(&metric->val, tmp); + cmt_atomic_store(&metric->timestamp, timestamp); +} + +static inline int metric_hist_exchange(struct cmt_metric *metric, + uint64_t timestamp, + int bucket_id, + uint64_t new, uint64_t old) +{ + int result; + + result = cmt_atomic_compare_exchange(&metric->hist_buckets[bucket_id], + old, new); + if (result == 0) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + return 1; +} + +void cmt_metric_hist_bucket_inc(struct cmt_metric *metric, uint64_t timestamp, + int bucket_id) +{ + int result; + uint64_t old; + uint64_t new; + + do { + old = cmt_atomic_load(&metric->hist_buckets[bucket_id]); + new = old + 1; + result = metric_hist_exchange(metric, timestamp, bucket_id, new, old); + } + while (result == 0); +} + + +void cmt_metric_inc(struct cmt_metric *metric, uint64_t timestamp) +{ + add(metric, timestamp, 1); +} + +void cmt_metric_dec(struct cmt_metric *metric, uint64_t timestamp) +{ + double volatile val = 1.0; + + add(metric, timestamp, val * -1); +} + +void cmt_metric_add(struct cmt_metric *metric, uint64_t timestamp, double val) +{ + add(metric, timestamp, val); +} + +void cmt_metric_sub(struct cmt_metric *metric, uint64_t timestamp, double val) +{ + add(metric, timestamp, (double volatile) val * -1); +} + +double cmt_metric_get_value(struct cmt_metric *metric) +{ + uint64_t val; + + val = cmt_atomic_load(&metric->val); + + return cmt_math_uint64_to_d64(val); +} + +uint64_t cmt_metric_get_timestamp(struct cmt_metric *metric) +{ + uint64_t val; + + val = cmt_atomic_load(&metric->timestamp); + + return val; +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_metric_histogram.c b/fluent-bit/lib/cmetrics/src/cmt_metric_histogram.c new file mode 100644 index 00000000..e2f7f063 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_metric_histogram.c @@ -0,0 +1,192 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_math.h> +#include <cmetrics/cmt_atomic.h> + +static inline int metric_hist_exchange(struct cmt_metric *metric, + uint64_t timestamp, + int bucket_id, + uint64_t new, uint64_t old) +{ + int result; + + result = cmt_atomic_compare_exchange(&metric->hist_buckets[bucket_id], + old, new); + if (result == 0) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + return 1; +} + +static inline int metric_hist_count_exchange(struct cmt_metric *metric, + uint64_t timestamp, + uint64_t new, uint64_t old) +{ + int result; + + result = cmt_atomic_compare_exchange(&metric->hist_count, old, new); + if (result == 0) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + return 1; +} + +static inline int metric_sum_exchange(struct cmt_metric *metric, + uint64_t timestamp, + double new_value, double old_value) +{ + uint64_t tmp_new; + uint64_t tmp_old; + int result; + + tmp_new = cmt_math_d64_to_uint64(new_value); + tmp_old = cmt_math_d64_to_uint64(old_value); + + result = cmt_atomic_compare_exchange(&metric->hist_sum, tmp_old, tmp_new); + + if (result == 0) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + return 1; +} + +void cmt_metric_hist_inc(struct cmt_metric *metric, uint64_t timestamp, + int bucket_id) +{ + int result; + uint64_t old; + uint64_t new; + + do { + old = cmt_atomic_load(&metric->hist_buckets[bucket_id]); + new = old + 1; + result = metric_hist_exchange(metric, timestamp, bucket_id, new, old); + } + while (result == 0); +} + +void cmt_metric_hist_count_inc(struct cmt_metric *metric, uint64_t timestamp) +{ + int result; + uint64_t old; + uint64_t new; + + do { + old = cmt_atomic_load(&metric->hist_count); + new = old + 1; + + result = metric_hist_count_exchange(metric, timestamp, new, old); + } + while (result == 0); +} + +void cmt_metric_hist_count_set(struct cmt_metric *metric, uint64_t timestamp, + uint64_t count) +{ + int result; + uint64_t old; + uint64_t new; + + do { + old = cmt_atomic_load(&metric->hist_count); + new = count; + + result = metric_hist_count_exchange(metric, timestamp, new, old); + } + while (result == 0); +} + +void cmt_metric_hist_sum_add(struct cmt_metric *metric, uint64_t timestamp, + double val) +{ + double old; + double new; + int result; + + do { + old = cmt_metric_hist_get_sum_value(metric); + new = old + val; + result = metric_sum_exchange(metric, timestamp, new, old); + } + while (0 == result); +} + +void cmt_metric_hist_sum_set(struct cmt_metric *metric, uint64_t timestamp, + double val) +{ + double old; + double new; + int result; + + do { + old = cmt_metric_hist_get_sum_value(metric); + new = val; + result = metric_sum_exchange(metric, timestamp, new, old); + } + while (0 == result); +} + +void cmt_metric_hist_set(struct cmt_metric *metric, uint64_t timestamp, + int bucket_id, double val) +{ + int result; + uint64_t old; + uint64_t new; + + do { + old = cmt_atomic_load(&metric->hist_buckets[bucket_id]); + new = val; + + result = metric_hist_exchange(metric, timestamp, bucket_id, new, old); + } + while (result == 0); +} + +uint64_t cmt_metric_hist_get_value(struct cmt_metric *metric, int bucket_id) +{ + uint64_t val; + + val = cmt_atomic_load(&metric->hist_buckets[bucket_id]); + return val; +} + +uint64_t cmt_metric_hist_get_count_value(struct cmt_metric *metric) +{ + uint64_t val; + + val = cmt_atomic_load(&metric->hist_count); + return val; +} + +double cmt_metric_hist_get_sum_value(struct cmt_metric *metric) +{ + uint64_t val; + + val = cmt_atomic_load(&metric->hist_sum); + return cmt_math_uint64_to_d64(val); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_mpack_utils.c b/fluent-bit/lib/cmetrics/src/cmt_mpack_utils.c new file mode 100644 index 00000000..e303554d --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_mpack_utils.c @@ -0,0 +1,286 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmt_mpack_utils.h> +#include <mpack/mpack.h> + +int cmt_mpack_consume_double_tag(mpack_reader_t *reader, double *output_buffer) +{ + mpack_tag_t tag; + + if (NULL == output_buffer) { + return CMT_MPACK_INVALID_ARGUMENT_ERROR; + } + + if (NULL == reader) { + return CMT_MPACK_INVALID_ARGUMENT_ERROR; + } + + tag = mpack_read_tag(reader); + + if (mpack_ok != mpack_reader_error(reader)) { + return CMT_MPACK_ENGINE_ERROR; + } + + if (mpack_type_double != mpack_tag_type(&tag)) { + return CMT_MPACK_UNEXPECTED_DATA_TYPE_ERROR; + } + + *output_buffer = mpack_tag_double_value(&tag); + + return CMT_MPACK_SUCCESS; +} + +int cmt_mpack_consume_uint_tag(mpack_reader_t *reader, uint64_t *output_buffer) +{ + mpack_tag_t tag; + + if (NULL == output_buffer) { + return CMT_MPACK_INVALID_ARGUMENT_ERROR; + } + + if (NULL == reader) { + return CMT_MPACK_INVALID_ARGUMENT_ERROR; + } + + tag = mpack_read_tag(reader); + + if (mpack_ok != mpack_reader_error(reader)) { + return CMT_MPACK_ENGINE_ERROR; + } + + if (mpack_type_uint != mpack_tag_type(&tag)) { + return CMT_MPACK_UNEXPECTED_DATA_TYPE_ERROR; + } + + *output_buffer = mpack_tag_uint_value(&tag); + + return CMT_MPACK_SUCCESS; +} + +int cmt_mpack_consume_string_tag(mpack_reader_t *reader, cfl_sds_t *output_buffer) +{ + uint32_t string_length; + mpack_tag_t tag; + + if (NULL == output_buffer) { + return CMT_MPACK_INVALID_ARGUMENT_ERROR; + } + + if (NULL == reader) { + return CMT_MPACK_INVALID_ARGUMENT_ERROR; + } + + tag = mpack_read_tag(reader); + + if (mpack_ok != mpack_reader_error(reader)) { + return CMT_MPACK_ENGINE_ERROR; + } + + if (mpack_type_str != mpack_tag_type(&tag)) { + return CMT_MPACK_UNEXPECTED_DATA_TYPE_ERROR; + } + + string_length = mpack_tag_str_length(&tag); + + /* This validation only applies to cmetrics and its use cases, we know + * for a fact that our label names and values are not supposed to be really + * long so a huge value here probably means that the data stream got corrupted. + */ + + if (CMT_MPACK_MAX_STRING_LENGTH < string_length) { + return CMT_MPACK_CORRUPT_INPUT_DATA_ERROR; + } + + *output_buffer = cfl_sds_create_size(string_length + 1); + + if (NULL == *output_buffer) { + return CMT_MPACK_ALLOCATION_ERROR; + } + + cfl_sds_set_len(*output_buffer, string_length); + + mpack_read_cstr(reader, *output_buffer, string_length + 1, string_length); + + if (mpack_ok != mpack_reader_error(reader)) { + cfl_sds_destroy(*output_buffer); + + *output_buffer = NULL; + + return CMT_MPACK_ENGINE_ERROR; + } + + mpack_done_str(reader); + + if (mpack_ok != mpack_reader_error(reader)) { + cfl_sds_destroy(*output_buffer); + + *output_buffer = NULL; + + return CMT_MPACK_ENGINE_ERROR; + } + + return CMT_MPACK_SUCCESS; +} + +int cmt_mpack_unpack_map(mpack_reader_t *reader, + struct cmt_mpack_map_entry_callback_t *callback_list, + void *context) +{ + struct cmt_mpack_map_entry_callback_t *callback_entry; + uint32_t entry_index; + uint32_t entry_count; + cfl_sds_t key_name; + int result; + mpack_tag_t tag; + + tag = mpack_read_tag(reader); + + if (mpack_ok != mpack_reader_error(reader)) { + return CMT_MPACK_ENGINE_ERROR; + } + + if (mpack_type_map != mpack_tag_type(&tag)) { + return CMT_MPACK_UNEXPECTED_DATA_TYPE_ERROR; + } + + entry_count = mpack_tag_map_count(&tag); + + /* This validation only applies to cmetrics and its use cases, we know + * how our schema looks and how many entries the different fields have and none + * of those exceed the number we set CMT_MPACK_MAX_MAP_ENTRY_COUNT to which is 10. + * Making these sanity checks optional or configurable in runtime might be worth + * the itme and complexity cost but that's something I don't know at the moment. + */ + + if (CMT_MPACK_MAX_MAP_ENTRY_COUNT < entry_count) { + return CMT_MPACK_CORRUPT_INPUT_DATA_ERROR; + } + + result = 0; + + for (entry_index = 0 ; 0 == result && entry_index < entry_count ; entry_index++) { + result = cmt_mpack_consume_string_tag(reader, &key_name); + + if (CMT_MPACK_SUCCESS == result) { + callback_entry = callback_list; + result = CMT_MPACK_UNEXPECTED_KEY_ERROR; + + while (CMT_MPACK_UNEXPECTED_KEY_ERROR == result && + NULL != callback_entry->identifier) { + + if (0 == strcmp(callback_entry->identifier, key_name)) { + result = callback_entry->handler(reader, entry_index, context); + } + + callback_entry++; + } + + cfl_sds_destroy(key_name); + } + } + + if (CMT_MPACK_SUCCESS == result) { + mpack_done_map(reader); + + if (mpack_ok != mpack_reader_error(reader)) + { + return CMT_MPACK_PENDING_MAP_ENTRIES; + } + } + + return result; +} + +int cmt_mpack_unpack_array(mpack_reader_t *reader, + cmt_mpack_unpacker_entry_callback_fn_t entry_processor_callback, + void *context) +{ + uint32_t entry_index; + uint32_t entry_count; + mpack_tag_t tag; + int result; + + tag = mpack_read_tag(reader); + + if (mpack_ok != mpack_reader_error(reader)) + { + return CMT_MPACK_ENGINE_ERROR; + } + + if (mpack_type_array != mpack_tag_type(&tag)) { + return CMT_MPACK_UNEXPECTED_DATA_TYPE_ERROR; + } + + entry_count = mpack_tag_array_count(&tag); + + /* This validation only applies to cmetrics and its use cases, we know + * that in our schema we have the following arrays : + * label text dictionary (strings) + * dimension labels (indexes) + * metric values + * dimension values + * + * IMO none of these arrays should be huge so I think using 65535 as a limit + * gives us more than enough wiggle space (in reality I don't expect any of these + * arrays to hold more than 128 values but I could be wrong as that probably depends + * on the flush interval) + */ + + if (CMT_MPACK_MAX_ARRAY_ENTRY_COUNT < entry_count) { + return CMT_MPACK_CORRUPT_INPUT_DATA_ERROR; + } + + result = CMT_MPACK_SUCCESS; + + for (entry_index = 0 ; + CMT_MPACK_SUCCESS == result && entry_index < entry_count ; + entry_index++) { + result = entry_processor_callback(reader, entry_index, context); + } + + if (CMT_MPACK_SUCCESS == result) { + mpack_done_array(reader); + + if (mpack_ok != mpack_reader_error(reader)) + { + return CMT_MPACK_PENDING_ARRAY_ENTRIES; + } + } + + return result; +} + +int cmt_mpack_peek_array_length(mpack_reader_t *reader) +{ + mpack_tag_t tag; + + tag = mpack_peek_tag(reader); + + if (mpack_ok != mpack_reader_error(reader)) + { + return 0; + } + + if (mpack_type_array != mpack_tag_type(&tag)) { + return 0; + } + + return mpack_tag_array_count(&tag); +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_opts.c b/fluent-bit/lib/cmetrics/src/cmt_opts.c new file mode 100644 index 00000000..b4f4cd2a --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_opts.c @@ -0,0 +1,118 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_opts.h> + +/* Initialize an 'opts' context with given values */ +int cmt_opts_init(struct cmt_opts *opts, + char *ns, char *subsystem, char *name, + char *description) +{ + int len; + cfl_sds_t tmp; + + if (!name) { + return -1; + } + + if (ns) { + opts->ns = cfl_sds_create(ns); + if (!opts->ns) { + return -1; + } + + opts->fqname = cfl_sds_create(ns); + if (!opts->fqname) { + return -1; + } + + if (strlen(ns) > 0) { + tmp = cfl_sds_cat(opts->fqname, "_", 1); + if (!tmp) { + return -1; + } + + opts->fqname = tmp; + } + } + + if (subsystem) { + opts->subsystem = cfl_sds_create(subsystem); + if (!opts->subsystem) { + return -1; + } + + if (strlen(opts->subsystem) > 0) { + tmp = cfl_sds_cat(opts->fqname, + opts->subsystem, cfl_sds_len(opts->subsystem)); + if (!tmp) { + return -1; + } + opts->fqname = tmp; + + len = cfl_sds_len(opts->fqname); + if (opts->fqname[len - 1] != '_') { + tmp = cfl_sds_cat(opts->fqname, "_", 1); + if (!tmp) { + return -1; + } + opts->fqname = tmp; + } + } + } + + opts->name = cfl_sds_create(name); + opts->description = cfl_sds_create(description); + + if (!opts->name || !opts->description) { + return -1; + } + + tmp = cfl_sds_cat(opts->fqname, opts->name, cfl_sds_len(opts->name)); + if (!tmp) { + return -1; + } + opts->fqname = tmp; + + return 0; +} + +void cmt_opts_exit(struct cmt_opts *opts) +{ + if (opts->ns) { + cfl_sds_destroy(opts->ns); + } + + if (opts->subsystem) { + cfl_sds_destroy(opts->subsystem); + } + + if (opts->name) { + cfl_sds_destroy(opts->name); + } + + if (opts->description) { + cfl_sds_destroy(opts->description); + } + + if (opts->fqname) { + cfl_sds_destroy(opts->fqname); + } +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_summary.c b/fluent-bit/lib/cmetrics/src/cmt_summary.c new file mode 100644 index 00000000..314fbfbe --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_summary.c @@ -0,0 +1,306 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_math.h> +#include <cmetrics/cmt_atomic.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_summary.h> + +#include <stdarg.h> + +/* + * CMetrics 'Summary' metric type is only a container for values reported by a + * scrapper. We don't do data observation or calculate values for quantiles, we + * just compose a structure to keep the reported values. + * + * This metric type uses very similar 'Histogram' structures and interfaces. + */ + +struct cmt_summary *cmt_summary_create(struct cmt *cmt, + char *ns, char *subsystem, + char *name, char *help, + size_t quantiles_count, + double *quantiles, + int label_count, char **label_keys) +{ + int i; + int ret; + struct cmt_summary *s; + + if (!ns) { + cmt_log_error(cmt, "null ns not allowed"); + return NULL; + } + + if (!subsystem) { + cmt_log_error(cmt, "null subsystem not allowed"); + return NULL; + } + + if (!name || strlen(name) == 0) { + cmt_log_error(cmt, "undefined name"); + return NULL; + } + + if (!help || strlen(help) == 0) { + cmt_log_error(cmt, "undefined help"); + return NULL; + } + + s = calloc(1, sizeof(struct cmt_summary)); + if (!s) { + cmt_errno(); + return NULL; + } + cfl_list_add(&s->_head, &cmt->summaries); + + /* initialize options */ + ret = cmt_opts_init(&s->opts, ns, subsystem, name, help); + if (ret == -1) { + cmt_log_error(cmt, "unable to initialize options for summary"); + cmt_summary_destroy(s); + return NULL; + } + + /* Create the map */ + s->map = cmt_map_create(CMT_SUMMARY, &s->opts, label_count, label_keys, + (void *) s); + if (!s->map) { + cmt_log_error(cmt, "unable to allocate map for summary"); + cmt_summary_destroy(s); + return NULL; + } + + /* create quantiles buffer */ + if (quantiles_count > 0) { + s->quantiles_count = quantiles_count; + s->quantiles = calloc(1, sizeof(double) * quantiles_count); + if (!s->quantiles_count) { + cmt_errno(); + cmt_summary_destroy(s); + return NULL; + } + + /* set quantile */ + for (i = 0; i < quantiles_count; i++) { + s->quantiles[i] = quantiles[i]; + } + } + + return s; +} + +int cmt_summary_destroy(struct cmt_summary *summary) +{ + cfl_list_del(&summary->_head); + cmt_opts_exit(&summary->opts); + + if (summary->map) { + cmt_map_destroy(summary->map); + } + + if (summary->quantiles) { + free(summary->quantiles); + } + + free(summary); + return 0; +} + +double cmt_summary_quantile_get_value(struct cmt_metric *metric, int quantile_id) +{ + uint64_t val; + + if (quantile_id < 0 /*|| quantile_id > metric->sum_quantiles_count*/) { + return 0; + } + + val = cmt_atomic_load(&metric->sum_quantiles[quantile_id]); + return cmt_math_uint64_to_d64(val); +} + +double cmt_summary_get_sum_value(struct cmt_metric *metric) +{ + uint64_t val; + + val = cmt_atomic_load(&metric->sum_sum); + return cmt_math_uint64_to_d64(val); +} + +uint64_t cmt_summary_get_count_value(struct cmt_metric *metric) +{ + uint64_t val; + + val = cmt_atomic_load(&metric->sum_count); + return val; +} + +static inline int summary_quantile_exchange(struct cmt_metric *metric, + uint64_t timestamp, + int quantile_id, + double new_value, double old_value) +{ + uint64_t tmp_new; + uint64_t tmp_old; + int result; + + tmp_new = cmt_math_d64_to_uint64(new_value); + tmp_old = cmt_math_d64_to_uint64(old_value); + + result = cmt_atomic_compare_exchange(&metric->sum_quantiles[quantile_id], + tmp_old, tmp_new); + + if (result == 0) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + return 1; +} + +static inline int summary_sum_exchange(struct cmt_metric *metric, + uint64_t timestamp, + double new_value, double old_value) +{ + uint64_t tmp_new; + uint64_t tmp_old; + int result; + + tmp_new = cmt_math_d64_to_uint64(new_value); + tmp_old = cmt_math_d64_to_uint64(old_value); + + result = cmt_atomic_compare_exchange(&metric->sum_sum, tmp_old, tmp_new); + + if (result == 0) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + return 1; +} + +static inline int summary_count_exchange(struct cmt_metric *metric, + uint64_t timestamp, + uint64_t new, uint64_t old) +{ + int result; + + result = cmt_atomic_compare_exchange(&metric->sum_count, old, new); + if (result == 0) { + return 0; + } + + cmt_atomic_store(&metric->timestamp, timestamp); + return 1; +} + +void cmt_summary_quantile_set(struct cmt_metric *metric, uint64_t timestamp, + int quantile_id, double val) +{ + double old; + double new; + int result; + + do { + old = cmt_summary_quantile_get_value(metric, quantile_id); + new = val; + result = summary_quantile_exchange(metric, timestamp, quantile_id, new, old); + } + while (0 == result); +} + +void cmt_summary_sum_set(struct cmt_metric *metric, uint64_t timestamp, double val) +{ + double old; + double new; + int result; + + do { + old = cmt_summary_get_sum_value(metric); + new = val; + result = summary_sum_exchange(metric, timestamp, new, old); + } + while (0 == result); +} + +void cmt_summary_count_set(struct cmt_metric *metric, uint64_t timestamp, + uint64_t count) +{ + int result; + uint64_t old; + uint64_t new; + + do { + old = cmt_atomic_load(&metric->sum_count); + new = count; + + result = summary_count_exchange(metric, timestamp, new, old); + } + while (result == 0); +} + +int cmt_summary_set_default(struct cmt_summary *summary, + uint64_t timestamp, + double *quantile_values, + double sum, + uint64_t count, + int labels_count, char **label_vars) +{ + int i; + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&summary->opts, summary->map, + labels_count, label_vars, + CMT_TRUE); + if (!metric) { + cmt_log_error(summary->cmt, "unable to retrieve metric: %s for summary %s_%s_%s", + summary->map, summary->opts.ns, summary->opts.subsystem, + summary->opts.name); + return -1; + } + + + if (!metric->sum_quantiles && summary->quantiles_count) { + metric->sum_quantiles = calloc(1, sizeof(uint64_t) * summary->quantiles_count); + if (!metric->sum_quantiles) { + cmt_errno(); + return -1; + } + metric->sum_quantiles_count = summary->quantiles_count; + } + + /* set quantile values */ + if (quantile_values) { + /* yes, quantile values are set */ + metric->sum_quantiles_set = CMT_TRUE; + + /* populate each quantile */ + for (i = 0; i < summary->quantiles_count; i++) { + cmt_summary_quantile_set(metric, timestamp, i, quantile_values[i]); + } + } + + cmt_summary_sum_set(metric, timestamp, sum); + cmt_summary_count_set(metric, timestamp, count); + + return 0; +}
\ No newline at end of file diff --git a/fluent-bit/lib/cmetrics/src/cmt_time.c b/fluent-bit/lib/cmetrics/src/cmt_time.c new file mode 100644 index 00000000..26bcfeb8 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_time.c @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmt_info.h> +#include <inttypes.h> +#include <time.h> + +void cmt_time_from_ns(struct timespec *tm, uint64_t ns) +{ + if (ns < 1000000000L) { + tm->tv_sec = 0; + tm->tv_nsec = ns; + } + else { + tm->tv_sec = ns / 1000000000L; + tm->tv_nsec = ns - (tm->tv_sec * 1000000000L); + } +} diff --git a/fluent-bit/lib/cmetrics/src/cmt_untyped.c b/fluent-bit/lib/cmetrics/src/cmt_untyped.c new file mode 100644 index 00000000..24af3990 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/cmt_untyped.c @@ -0,0 +1,140 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2022 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cmetrics/cmetrics.h> +#include <cmetrics/cmt_log.h> +#include <cmetrics/cmt_map.h> +#include <cmetrics/cmt_metric.h> +#include <cmetrics/cmt_untyped.h> + +struct cmt_untyped *cmt_untyped_create(struct cmt *cmt, + char *ns, char *subsystem, + char *name, char *help, + int label_count, char **label_keys) +{ + int ret; + struct cmt_untyped *untyped; + + if (!ns) { + cmt_log_error(cmt, "null ns not allowed"); + return NULL; + } + + if (!subsystem) { + cmt_log_error(cmt, "null subsystem not allowed"); + return NULL; + } + + if (!help || strlen(help) == 0) { + cmt_log_error(cmt, "undefined help"); + return NULL; + } + + if (!name || strlen(name) == 0) { + cmt_log_error(cmt, "undefined name"); + return NULL; + } + + if (!help || strlen(help) == 0) { + cmt_log_error(cmt, "undefined help"); + return NULL; + } + + untyped = calloc(1, sizeof(struct cmt_untyped)); + if (!untyped) { + cmt_errno(); + return NULL; + } + cfl_list_add(&untyped->_head, &cmt->untypeds); + + ret = cmt_opts_init(&untyped->opts, ns, subsystem, name, help); + if (ret == -1) { + cmt_log_error(cmt, "unable to initialize options for untyped"); + cmt_untyped_destroy(untyped); + return NULL; + } + + /* Create the map */ + untyped->map = cmt_map_create(CMT_UNTYPED, &untyped->opts, label_count, label_keys, + (void *) untyped); + if (!untyped->map) { + cmt_log_error(cmt, "unable to allocate map for untyped"); + cmt_untyped_destroy(untyped); + return NULL; + } + + untyped->cmt = cmt; + + return untyped; +} + +int cmt_untyped_destroy(struct cmt_untyped *untyped) +{ + cfl_list_del(&untyped->_head); + cmt_opts_exit(&untyped->opts); + + if (untyped->map) { + cmt_map_destroy(untyped->map); + } + free(untyped); + return 0; +} + +/* Set untyped value, new value cannot be smaller than current value */ +int cmt_untyped_set(struct cmt_untyped *untyped, uint64_t timestamp, double val, + int labels_count, char **label_vals) +{ + struct cmt_metric *metric; + + metric = cmt_map_metric_get(&untyped->opts, untyped->map, + labels_count, label_vals, + CMT_TRUE); + if (!metric) { + cmt_log_error(untyped->cmt, "unable to retrieve metric: %s for untyped %s_%s_%s", + untyped->map, untyped->opts.ns, untyped->opts.subsystem, + untyped->opts.name); + return -1; + } + + if (cmt_metric_get_value(metric) > val) { + return -1; + } + cmt_metric_set(metric, timestamp, val); + return 0; +} + +int cmt_untyped_get_val(struct cmt_untyped *untyped, + int labels_count, char **label_vals, double *out_val) +{ + int ret; + double val = 0; + + ret = cmt_map_metric_get_val(&untyped->opts, + untyped->map, labels_count, label_vals, + &val); + if (ret == -1) { + cmt_log_error(untyped->cmt, + "unable to retrieve metric value: %s for untyped %s_%s_%s", + untyped->map, untyped->opts.ns, untyped->opts.subsystem, + untyped->opts.name); + return -1; + } + *out_val = val; + return 0; +} diff --git a/fluent-bit/lib/cmetrics/src/external/LICENSE b/fluent-bit/lib/cmetrics/src/external/LICENSE new file mode 100644 index 00000000..c1c6ac95 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/LICENSE @@ -0,0 +1,32 @@ +Copyright (c) 2008-2016, Dave Benson and the protobuf-c authors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The code generated by the protoc-gen-c code generator and by the +protoc-c compiler is owned by the owner of the input files used when +generating it. This code is not standalone and requires a support +library to be linked with it. This support library is covered by the +above license. diff --git a/fluent-bit/lib/cmetrics/src/external/opentelemetry_common.pb-c.c b/fluent-bit/lib/cmetrics/src/external/opentelemetry_common.pb-c.c new file mode 100644 index 00000000..3eb1fd5b --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/opentelemetry_common.pb-c.c @@ -0,0 +1,624 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: common.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include <opentelemetry/common.pb-c.h> +void opentelemetry__proto__common__v1__any_value__init + (Opentelemetry__Proto__Common__V1__AnyValue *message) +{ + static const Opentelemetry__Proto__Common__V1__AnyValue init_value = OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__INIT; + *message = init_value; +} +size_t opentelemetry__proto__common__v1__any_value__get_packed_size + (const Opentelemetry__Proto__Common__V1__AnyValue *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__any_value__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__common__v1__any_value__pack + (const Opentelemetry__Proto__Common__V1__AnyValue *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__any_value__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__common__v1__any_value__pack_to_buffer + (const Opentelemetry__Proto__Common__V1__AnyValue *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__any_value__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Common__V1__AnyValue * + opentelemetry__proto__common__v1__any_value__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Common__V1__AnyValue *) + protobuf_c_message_unpack (&opentelemetry__proto__common__v1__any_value__descriptor, + allocator, len, data); +} +void opentelemetry__proto__common__v1__any_value__free_unpacked + (Opentelemetry__Proto__Common__V1__AnyValue *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__common__v1__any_value__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__common__v1__array_value__init + (Opentelemetry__Proto__Common__V1__ArrayValue *message) +{ + static const Opentelemetry__Proto__Common__V1__ArrayValue init_value = OPENTELEMETRY__PROTO__COMMON__V1__ARRAY_VALUE__INIT; + *message = init_value; +} +size_t opentelemetry__proto__common__v1__array_value__get_packed_size + (const Opentelemetry__Proto__Common__V1__ArrayValue *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__array_value__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__common__v1__array_value__pack + (const Opentelemetry__Proto__Common__V1__ArrayValue *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__array_value__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__common__v1__array_value__pack_to_buffer + (const Opentelemetry__Proto__Common__V1__ArrayValue *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__array_value__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Common__V1__ArrayValue * + opentelemetry__proto__common__v1__array_value__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Common__V1__ArrayValue *) + protobuf_c_message_unpack (&opentelemetry__proto__common__v1__array_value__descriptor, + allocator, len, data); +} +void opentelemetry__proto__common__v1__array_value__free_unpacked + (Opentelemetry__Proto__Common__V1__ArrayValue *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__common__v1__array_value__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__common__v1__key_value_list__init + (Opentelemetry__Proto__Common__V1__KeyValueList *message) +{ + static const Opentelemetry__Proto__Common__V1__KeyValueList init_value = OPENTELEMETRY__PROTO__COMMON__V1__KEY_VALUE_LIST__INIT; + *message = init_value; +} +size_t opentelemetry__proto__common__v1__key_value_list__get_packed_size + (const Opentelemetry__Proto__Common__V1__KeyValueList *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value_list__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__common__v1__key_value_list__pack + (const Opentelemetry__Proto__Common__V1__KeyValueList *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value_list__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__common__v1__key_value_list__pack_to_buffer + (const Opentelemetry__Proto__Common__V1__KeyValueList *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value_list__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Common__V1__KeyValueList * + opentelemetry__proto__common__v1__key_value_list__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Common__V1__KeyValueList *) + protobuf_c_message_unpack (&opentelemetry__proto__common__v1__key_value_list__descriptor, + allocator, len, data); +} +void opentelemetry__proto__common__v1__key_value_list__free_unpacked + (Opentelemetry__Proto__Common__V1__KeyValueList *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value_list__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__common__v1__key_value__init + (Opentelemetry__Proto__Common__V1__KeyValue *message) +{ + static const Opentelemetry__Proto__Common__V1__KeyValue init_value = OPENTELEMETRY__PROTO__COMMON__V1__KEY_VALUE__INIT; + *message = init_value; +} +size_t opentelemetry__proto__common__v1__key_value__get_packed_size + (const Opentelemetry__Proto__Common__V1__KeyValue *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__common__v1__key_value__pack + (const Opentelemetry__Proto__Common__V1__KeyValue *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__common__v1__key_value__pack_to_buffer + (const Opentelemetry__Proto__Common__V1__KeyValue *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Common__V1__KeyValue * + opentelemetry__proto__common__v1__key_value__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Common__V1__KeyValue *) + protobuf_c_message_unpack (&opentelemetry__proto__common__v1__key_value__descriptor, + allocator, len, data); +} +void opentelemetry__proto__common__v1__key_value__free_unpacked + (Opentelemetry__Proto__Common__V1__KeyValue *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__common__v1__key_value__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__common__v1__string_key_value__init + (Opentelemetry__Proto__Common__V1__StringKeyValue *message) +{ + static const Opentelemetry__Proto__Common__V1__StringKeyValue init_value = OPENTELEMETRY__PROTO__COMMON__V1__STRING_KEY_VALUE__INIT; + *message = init_value; +} +size_t opentelemetry__proto__common__v1__string_key_value__get_packed_size + (const Opentelemetry__Proto__Common__V1__StringKeyValue *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__string_key_value__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__common__v1__string_key_value__pack + (const Opentelemetry__Proto__Common__V1__StringKeyValue *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__string_key_value__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__common__v1__string_key_value__pack_to_buffer + (const Opentelemetry__Proto__Common__V1__StringKeyValue *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__string_key_value__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Common__V1__StringKeyValue * + opentelemetry__proto__common__v1__string_key_value__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Common__V1__StringKeyValue *) + protobuf_c_message_unpack (&opentelemetry__proto__common__v1__string_key_value__descriptor, + allocator, len, data); +} +void opentelemetry__proto__common__v1__string_key_value__free_unpacked + (Opentelemetry__Proto__Common__V1__StringKeyValue *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__common__v1__string_key_value__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__common__v1__instrumentation_library__init + (Opentelemetry__Proto__Common__V1__InstrumentationLibrary *message) +{ + static const Opentelemetry__Proto__Common__V1__InstrumentationLibrary init_value = OPENTELEMETRY__PROTO__COMMON__V1__INSTRUMENTATION_LIBRARY__INIT; + *message = init_value; +} +size_t opentelemetry__proto__common__v1__instrumentation_library__get_packed_size + (const Opentelemetry__Proto__Common__V1__InstrumentationLibrary *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__instrumentation_library__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__common__v1__instrumentation_library__pack + (const Opentelemetry__Proto__Common__V1__InstrumentationLibrary *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__instrumentation_library__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__common__v1__instrumentation_library__pack_to_buffer + (const Opentelemetry__Proto__Common__V1__InstrumentationLibrary *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__common__v1__instrumentation_library__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Common__V1__InstrumentationLibrary * + opentelemetry__proto__common__v1__instrumentation_library__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Common__V1__InstrumentationLibrary *) + protobuf_c_message_unpack (&opentelemetry__proto__common__v1__instrumentation_library__descriptor, + allocator, len, data); +} +void opentelemetry__proto__common__v1__instrumentation_library__free_unpacked + (Opentelemetry__Proto__Common__V1__InstrumentationLibrary *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__common__v1__instrumentation_library__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor opentelemetry__proto__common__v1__any_value__field_descriptors[7] = +{ + { + "string_value", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, value_case), + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, string_value), + NULL, + &protobuf_c_empty_string, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "bool_value", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, value_case), + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, bool_value), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "int_value", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, value_case), + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, int_value), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "double_value", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, value_case), + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, double_value), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "array_value", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, value_case), + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, array_value), + &opentelemetry__proto__common__v1__array_value__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "kvlist_value", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, value_case), + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, kvlist_value), + &opentelemetry__proto__common__v1__key_value_list__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "bytes_value", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, value_case), + offsetof(Opentelemetry__Proto__Common__V1__AnyValue, bytes_value), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__common__v1__any_value__field_indices_by_name[] = { + 4, /* field[4] = array_value */ + 1, /* field[1] = bool_value */ + 6, /* field[6] = bytes_value */ + 3, /* field[3] = double_value */ + 2, /* field[2] = int_value */ + 5, /* field[5] = kvlist_value */ + 0, /* field[0] = string_value */ +}; +static const ProtobufCIntRange opentelemetry__proto__common__v1__any_value__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__common__v1__any_value__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.common.v1.AnyValue", + "AnyValue", + "Opentelemetry__Proto__Common__V1__AnyValue", + "opentelemetry.proto.common.v1", + sizeof(Opentelemetry__Proto__Common__V1__AnyValue), + 7, + opentelemetry__proto__common__v1__any_value__field_descriptors, + opentelemetry__proto__common__v1__any_value__field_indices_by_name, + 1, opentelemetry__proto__common__v1__any_value__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__common__v1__any_value__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__common__v1__array_value__field_descriptors[1] = +{ + { + "values", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Common__V1__ArrayValue, n_values), + offsetof(Opentelemetry__Proto__Common__V1__ArrayValue, values), + &opentelemetry__proto__common__v1__any_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__common__v1__array_value__field_indices_by_name[] = { + 0, /* field[0] = values */ +}; +static const ProtobufCIntRange opentelemetry__proto__common__v1__array_value__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__common__v1__array_value__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.common.v1.ArrayValue", + "ArrayValue", + "Opentelemetry__Proto__Common__V1__ArrayValue", + "opentelemetry.proto.common.v1", + sizeof(Opentelemetry__Proto__Common__V1__ArrayValue), + 1, + opentelemetry__proto__common__v1__array_value__field_descriptors, + opentelemetry__proto__common__v1__array_value__field_indices_by_name, + 1, opentelemetry__proto__common__v1__array_value__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__common__v1__array_value__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__common__v1__key_value_list__field_descriptors[1] = +{ + { + "values", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Common__V1__KeyValueList, n_values), + offsetof(Opentelemetry__Proto__Common__V1__KeyValueList, values), + &opentelemetry__proto__common__v1__key_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__common__v1__key_value_list__field_indices_by_name[] = { + 0, /* field[0] = values */ +}; +static const ProtobufCIntRange opentelemetry__proto__common__v1__key_value_list__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__common__v1__key_value_list__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.common.v1.KeyValueList", + "KeyValueList", + "Opentelemetry__Proto__Common__V1__KeyValueList", + "opentelemetry.proto.common.v1", + sizeof(Opentelemetry__Proto__Common__V1__KeyValueList), + 1, + opentelemetry__proto__common__v1__key_value_list__field_descriptors, + opentelemetry__proto__common__v1__key_value_list__field_indices_by_name, + 1, opentelemetry__proto__common__v1__key_value_list__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__common__v1__key_value_list__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__common__v1__key_value__field_descriptors[2] = +{ + { + "key", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Common__V1__KeyValue, key), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Common__V1__KeyValue, value), + &opentelemetry__proto__common__v1__any_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__common__v1__key_value__field_indices_by_name[] = { + 0, /* field[0] = key */ + 1, /* field[1] = value */ +}; +static const ProtobufCIntRange opentelemetry__proto__common__v1__key_value__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__common__v1__key_value__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.common.v1.KeyValue", + "KeyValue", + "Opentelemetry__Proto__Common__V1__KeyValue", + "opentelemetry.proto.common.v1", + sizeof(Opentelemetry__Proto__Common__V1__KeyValue), + 2, + opentelemetry__proto__common__v1__key_value__field_descriptors, + opentelemetry__proto__common__v1__key_value__field_indices_by_name, + 1, opentelemetry__proto__common__v1__key_value__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__common__v1__key_value__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__common__v1__string_key_value__field_descriptors[2] = +{ + { + "key", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Common__V1__StringKeyValue, key), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Common__V1__StringKeyValue, value), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__common__v1__string_key_value__field_indices_by_name[] = { + 0, /* field[0] = key */ + 1, /* field[1] = value */ +}; +static const ProtobufCIntRange opentelemetry__proto__common__v1__string_key_value__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__common__v1__string_key_value__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.common.v1.StringKeyValue", + "StringKeyValue", + "Opentelemetry__Proto__Common__V1__StringKeyValue", + "opentelemetry.proto.common.v1", + sizeof(Opentelemetry__Proto__Common__V1__StringKeyValue), + 2, + opentelemetry__proto__common__v1__string_key_value__field_descriptors, + opentelemetry__proto__common__v1__string_key_value__field_indices_by_name, + 1, opentelemetry__proto__common__v1__string_key_value__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__common__v1__string_key_value__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__common__v1__instrumentation_library__field_descriptors[2] = +{ + { + "name", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Common__V1__InstrumentationLibrary, name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "version", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Common__V1__InstrumentationLibrary, version), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__common__v1__instrumentation_library__field_indices_by_name[] = { + 0, /* field[0] = name */ + 1, /* field[1] = version */ +}; +static const ProtobufCIntRange opentelemetry__proto__common__v1__instrumentation_library__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__common__v1__instrumentation_library__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.common.v1.InstrumentationLibrary", + "InstrumentationLibrary", + "Opentelemetry__Proto__Common__V1__InstrumentationLibrary", + "opentelemetry.proto.common.v1", + sizeof(Opentelemetry__Proto__Common__V1__InstrumentationLibrary), + 2, + opentelemetry__proto__common__v1__instrumentation_library__field_descriptors, + opentelemetry__proto__common__v1__instrumentation_library__field_indices_by_name, + 1, opentelemetry__proto__common__v1__instrumentation_library__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__common__v1__instrumentation_library__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics.pb-c.c b/fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics.pb-c.c new file mode 100644 index 00000000..7452586c --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics.pb-c.c @@ -0,0 +1,1996 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: otlp_metrics.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include <opentelemetry/metrics.pb-c.h> +void opentelemetry__proto__metrics__v1__metrics_data__init + (Opentelemetry__Proto__Metrics__V1__MetricsData *message) +{ + static const Opentelemetry__Proto__Metrics__V1__MetricsData init_value = OPENTELEMETRY__PROTO__METRICS__V1__METRICS_DATA__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__metrics_data__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__MetricsData *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metrics_data__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__metrics_data__pack + (const Opentelemetry__Proto__Metrics__V1__MetricsData *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metrics_data__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__metrics_data__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__MetricsData *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metrics_data__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__MetricsData * + opentelemetry__proto__metrics__v1__metrics_data__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__MetricsData *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__metrics_data__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__metrics_data__free_unpacked + (Opentelemetry__Proto__Metrics__V1__MetricsData *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metrics_data__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__resource_metrics__init + (Opentelemetry__Proto__Metrics__V1__ResourceMetrics *message) +{ + static const Opentelemetry__Proto__Metrics__V1__ResourceMetrics init_value = OPENTELEMETRY__PROTO__METRICS__V1__RESOURCE_METRICS__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__resource_metrics__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__ResourceMetrics *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__resource_metrics__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__resource_metrics__pack + (const Opentelemetry__Proto__Metrics__V1__ResourceMetrics *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__resource_metrics__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__resource_metrics__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__ResourceMetrics *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__resource_metrics__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__ResourceMetrics * + opentelemetry__proto__metrics__v1__resource_metrics__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__ResourceMetrics *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__resource_metrics__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__resource_metrics__free_unpacked + (Opentelemetry__Proto__Metrics__V1__ResourceMetrics *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__resource_metrics__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__instrumentation_library_metrics__init + (Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics *message) +{ + static const Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics init_value = OPENTELEMETRY__PROTO__METRICS__V1__INSTRUMENTATION_LIBRARY_METRICS__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__instrumentation_library_metrics__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__instrumentation_library_metrics__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__instrumentation_library_metrics__pack + (const Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__instrumentation_library_metrics__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__instrumentation_library_metrics__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__instrumentation_library_metrics__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics * + opentelemetry__proto__metrics__v1__instrumentation_library_metrics__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__instrumentation_library_metrics__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__instrumentation_library_metrics__free_unpacked + (Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__instrumentation_library_metrics__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__metric__init + (Opentelemetry__Proto__Metrics__V1__Metric *message) +{ + static const Opentelemetry__Proto__Metrics__V1__Metric init_value = OPENTELEMETRY__PROTO__METRICS__V1__METRIC__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__metric__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__Metric *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metric__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__metric__pack + (const Opentelemetry__Proto__Metrics__V1__Metric *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metric__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__metric__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__Metric *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metric__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__Metric * + opentelemetry__proto__metrics__v1__metric__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__Metric *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__metric__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__metric__free_unpacked + (Opentelemetry__Proto__Metrics__V1__Metric *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__metric__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__gauge__init + (Opentelemetry__Proto__Metrics__V1__Gauge *message) +{ + static const Opentelemetry__Proto__Metrics__V1__Gauge init_value = OPENTELEMETRY__PROTO__METRICS__V1__GAUGE__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__gauge__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__Gauge *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__gauge__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__gauge__pack + (const Opentelemetry__Proto__Metrics__V1__Gauge *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__gauge__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__gauge__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__Gauge *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__gauge__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__Gauge * + opentelemetry__proto__metrics__v1__gauge__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__Gauge *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__gauge__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__gauge__free_unpacked + (Opentelemetry__Proto__Metrics__V1__Gauge *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__gauge__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__sum__init + (Opentelemetry__Proto__Metrics__V1__Sum *message) +{ + static const Opentelemetry__Proto__Metrics__V1__Sum init_value = OPENTELEMETRY__PROTO__METRICS__V1__SUM__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__sum__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__Sum *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__sum__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__sum__pack + (const Opentelemetry__Proto__Metrics__V1__Sum *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__sum__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__sum__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__Sum *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__sum__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__Sum * + opentelemetry__proto__metrics__v1__sum__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__Sum *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__sum__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__sum__free_unpacked + (Opentelemetry__Proto__Metrics__V1__Sum *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__sum__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__histogram__init + (Opentelemetry__Proto__Metrics__V1__Histogram *message) +{ + static const Opentelemetry__Proto__Metrics__V1__Histogram init_value = OPENTELEMETRY__PROTO__METRICS__V1__HISTOGRAM__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__histogram__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__Histogram *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__histogram__pack + (const Opentelemetry__Proto__Metrics__V1__Histogram *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__histogram__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__Histogram *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__Histogram * + opentelemetry__proto__metrics__v1__histogram__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__Histogram *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__histogram__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__histogram__free_unpacked + (Opentelemetry__Proto__Metrics__V1__Histogram *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__exponential_histogram__init + (Opentelemetry__Proto__Metrics__V1__ExponentialHistogram *message) +{ + static const Opentelemetry__Proto__Metrics__V1__ExponentialHistogram init_value = OPENTELEMETRY__PROTO__METRICS__V1__EXPONENTIAL_HISTOGRAM__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__exponential_histogram__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__ExponentialHistogram *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__exponential_histogram__pack + (const Opentelemetry__Proto__Metrics__V1__ExponentialHistogram *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__exponential_histogram__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__ExponentialHistogram *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__ExponentialHistogram * + opentelemetry__proto__metrics__v1__exponential_histogram__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__ExponentialHistogram *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__exponential_histogram__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__exponential_histogram__free_unpacked + (Opentelemetry__Proto__Metrics__V1__ExponentialHistogram *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__summary__init + (Opentelemetry__Proto__Metrics__V1__Summary *message) +{ + static const Opentelemetry__Proto__Metrics__V1__Summary init_value = OPENTELEMETRY__PROTO__METRICS__V1__SUMMARY__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__summary__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__Summary *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__summary__pack + (const Opentelemetry__Proto__Metrics__V1__Summary *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__summary__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__Summary *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__Summary * + opentelemetry__proto__metrics__v1__summary__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__Summary *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__summary__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__summary__free_unpacked + (Opentelemetry__Proto__Metrics__V1__Summary *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__number_data_point__init + (Opentelemetry__Proto__Metrics__V1__NumberDataPoint *message) +{ + static const Opentelemetry__Proto__Metrics__V1__NumberDataPoint init_value = OPENTELEMETRY__PROTO__METRICS__V1__NUMBER_DATA_POINT__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__number_data_point__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__NumberDataPoint *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__number_data_point__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__number_data_point__pack + (const Opentelemetry__Proto__Metrics__V1__NumberDataPoint *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__number_data_point__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__number_data_point__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__NumberDataPoint *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__number_data_point__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__NumberDataPoint * + opentelemetry__proto__metrics__v1__number_data_point__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__NumberDataPoint *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__number_data_point__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__number_data_point__free_unpacked + (Opentelemetry__Proto__Metrics__V1__NumberDataPoint *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__number_data_point__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__histogram_data_point__init + (Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *message) +{ + static const Opentelemetry__Proto__Metrics__V1__HistogramDataPoint init_value = OPENTELEMETRY__PROTO__METRICS__V1__HISTOGRAM_DATA_POINT__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__histogram_data_point__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram_data_point__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__histogram_data_point__pack + (const Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram_data_point__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__histogram_data_point__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram_data_point__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__HistogramDataPoint * + opentelemetry__proto__metrics__v1__histogram_data_point__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__histogram_data_point__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__histogram_data_point__free_unpacked + (Opentelemetry__Proto__Metrics__V1__HistogramDataPoint *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__histogram_data_point__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__init + (Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint__Buckets *message) +{ + static const Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint__Buckets init_value = OPENTELEMETRY__PROTO__METRICS__V1__EXPONENTIAL_HISTOGRAM_DATA_POINT__BUCKETS__INIT; + *message = init_value; +} +void opentelemetry__proto__metrics__v1__exponential_histogram_data_point__init + (Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint *message) +{ + static const Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint init_value = OPENTELEMETRY__PROTO__METRICS__V1__EXPONENTIAL_HISTOGRAM_DATA_POINT__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__exponential_histogram_data_point__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram_data_point__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__exponential_histogram_data_point__pack + (const Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram_data_point__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__exponential_histogram_data_point__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram_data_point__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint * + opentelemetry__proto__metrics__v1__exponential_histogram_data_point__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__exponential_histogram_data_point__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__exponential_histogram_data_point__free_unpacked + (Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exponential_histogram_data_point__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__init + (Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile *message) +{ + static const Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile init_value = OPENTELEMETRY__PROTO__METRICS__V1__SUMMARY_DATA_POINT__VALUE_AT_QUANTILE__INIT; + *message = init_value; +} +void opentelemetry__proto__metrics__v1__summary_data_point__init + (Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *message) +{ + static const Opentelemetry__Proto__Metrics__V1__SummaryDataPoint init_value = OPENTELEMETRY__PROTO__METRICS__V1__SUMMARY_DATA_POINT__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__summary_data_point__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary_data_point__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__summary_data_point__pack + (const Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary_data_point__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__summary_data_point__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary_data_point__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__SummaryDataPoint * + opentelemetry__proto__metrics__v1__summary_data_point__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__summary_data_point__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__summary_data_point__free_unpacked + (Opentelemetry__Proto__Metrics__V1__SummaryDataPoint *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__summary_data_point__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__metrics__v1__exemplar__init + (Opentelemetry__Proto__Metrics__V1__Exemplar *message) +{ + static const Opentelemetry__Proto__Metrics__V1__Exemplar init_value = OPENTELEMETRY__PROTO__METRICS__V1__EXEMPLAR__INIT; + *message = init_value; +} +size_t opentelemetry__proto__metrics__v1__exemplar__get_packed_size + (const Opentelemetry__Proto__Metrics__V1__Exemplar *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exemplar__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__metrics__v1__exemplar__pack + (const Opentelemetry__Proto__Metrics__V1__Exemplar *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exemplar__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__metrics__v1__exemplar__pack_to_buffer + (const Opentelemetry__Proto__Metrics__V1__Exemplar *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exemplar__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Metrics__V1__Exemplar * + opentelemetry__proto__metrics__v1__exemplar__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Metrics__V1__Exemplar *) + protobuf_c_message_unpack (&opentelemetry__proto__metrics__v1__exemplar__descriptor, + allocator, len, data); +} +void opentelemetry__proto__metrics__v1__exemplar__free_unpacked + (Opentelemetry__Proto__Metrics__V1__Exemplar *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__metrics__v1__exemplar__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__metrics_data__field_descriptors[1] = +{ + { + "resource_metrics", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__MetricsData, n_resource_metrics), + offsetof(Opentelemetry__Proto__Metrics__V1__MetricsData, resource_metrics), + &opentelemetry__proto__metrics__v1__resource_metrics__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__metrics_data__field_indices_by_name[] = { + 0, /* field[0] = resource_metrics */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__metrics_data__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__metrics_data__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.MetricsData", + "MetricsData", + "Opentelemetry__Proto__Metrics__V1__MetricsData", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__MetricsData), + 1, + opentelemetry__proto__metrics__v1__metrics_data__field_descriptors, + opentelemetry__proto__metrics__v1__metrics_data__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__metrics_data__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__metrics_data__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__resource_metrics__field_descriptors[3] = +{ + { + "resource", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ResourceMetrics, resource), + &opentelemetry__proto__resource__v1__resource__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "instrumentation_library_metrics", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__ResourceMetrics, n_instrumentation_library_metrics), + offsetof(Opentelemetry__Proto__Metrics__V1__ResourceMetrics, instrumentation_library_metrics), + &opentelemetry__proto__metrics__v1__instrumentation_library_metrics__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "schema_url", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ResourceMetrics, schema_url), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__resource_metrics__field_indices_by_name[] = { + 1, /* field[1] = instrumentation_library_metrics */ + 0, /* field[0] = resource */ + 2, /* field[2] = schema_url */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__resource_metrics__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__resource_metrics__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.ResourceMetrics", + "ResourceMetrics", + "Opentelemetry__Proto__Metrics__V1__ResourceMetrics", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__ResourceMetrics), + 3, + opentelemetry__proto__metrics__v1__resource_metrics__field_descriptors, + opentelemetry__proto__metrics__v1__resource_metrics__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__resource_metrics__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__resource_metrics__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__instrumentation_library_metrics__field_descriptors[3] = +{ + { + "instrumentation_library", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics, instrumentation_library), + &opentelemetry__proto__common__v1__instrumentation_library__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "metrics", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics, n_metrics), + offsetof(Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics, metrics), + &opentelemetry__proto__metrics__v1__metric__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "schema_url", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics, schema_url), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__instrumentation_library_metrics__field_indices_by_name[] = { + 0, /* field[0] = instrumentation_library */ + 1, /* field[1] = metrics */ + 2, /* field[2] = schema_url */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__instrumentation_library_metrics__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__instrumentation_library_metrics__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.InstrumentationLibraryMetrics", + "InstrumentationLibraryMetrics", + "Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__InstrumentationLibraryMetrics), + 3, + opentelemetry__proto__metrics__v1__instrumentation_library_metrics__field_descriptors, + opentelemetry__proto__metrics__v1__instrumentation_library_metrics__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__instrumentation_library_metrics__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__instrumentation_library_metrics__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__metric__field_descriptors[8] = +{ + { + "name", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "description", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, description), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "unit", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, unit), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "gauge", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, data_case), + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, gauge), + &opentelemetry__proto__metrics__v1__gauge__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "sum", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, data_case), + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, sum), + &opentelemetry__proto__metrics__v1__sum__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "histogram", + 9, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, data_case), + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, histogram), + &opentelemetry__proto__metrics__v1__histogram__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "exponential_histogram", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, data_case), + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, exponential_histogram), + &opentelemetry__proto__metrics__v1__exponential_histogram__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "summary", + 11, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, data_case), + offsetof(Opentelemetry__Proto__Metrics__V1__Metric, summary), + &opentelemetry__proto__metrics__v1__summary__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__metric__field_indices_by_name[] = { + 1, /* field[1] = description */ + 6, /* field[6] = exponential_histogram */ + 3, /* field[3] = gauge */ + 5, /* field[5] = histogram */ + 0, /* field[0] = name */ + 4, /* field[4] = sum */ + 7, /* field[7] = summary */ + 2, /* field[2] = unit */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__metric__number_ranges[4 + 1] = +{ + { 1, 0 }, + { 5, 3 }, + { 7, 4 }, + { 9, 5 }, + { 0, 8 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__metric__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.Metric", + "Metric", + "Opentelemetry__Proto__Metrics__V1__Metric", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__Metric), + 8, + opentelemetry__proto__metrics__v1__metric__field_descriptors, + opentelemetry__proto__metrics__v1__metric__field_indices_by_name, + 4, opentelemetry__proto__metrics__v1__metric__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__metric__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__gauge__field_descriptors[1] = +{ + { + "data_points", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Gauge, n_data_points), + offsetof(Opentelemetry__Proto__Metrics__V1__Gauge, data_points), + &opentelemetry__proto__metrics__v1__number_data_point__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__gauge__field_indices_by_name[] = { + 0, /* field[0] = data_points */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__gauge__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__gauge__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.Gauge", + "Gauge", + "Opentelemetry__Proto__Metrics__V1__Gauge", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__Gauge), + 1, + opentelemetry__proto__metrics__v1__gauge__field_descriptors, + opentelemetry__proto__metrics__v1__gauge__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__gauge__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__gauge__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__sum__field_descriptors[3] = +{ + { + "data_points", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Sum, n_data_points), + offsetof(Opentelemetry__Proto__Metrics__V1__Sum, data_points), + &opentelemetry__proto__metrics__v1__number_data_point__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "aggregation_temporality", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Sum, aggregation_temporality), + &opentelemetry__proto__metrics__v1__aggregation_temporality__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "is_monotonic", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Sum, is_monotonic), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__sum__field_indices_by_name[] = { + 1, /* field[1] = aggregation_temporality */ + 0, /* field[0] = data_points */ + 2, /* field[2] = is_monotonic */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__sum__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__sum__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.Sum", + "Sum", + "Opentelemetry__Proto__Metrics__V1__Sum", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__Sum), + 3, + opentelemetry__proto__metrics__v1__sum__field_descriptors, + opentelemetry__proto__metrics__v1__sum__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__sum__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__sum__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__histogram__field_descriptors[2] = +{ + { + "data_points", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Histogram, n_data_points), + offsetof(Opentelemetry__Proto__Metrics__V1__Histogram, data_points), + &opentelemetry__proto__metrics__v1__histogram_data_point__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "aggregation_temporality", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Histogram, aggregation_temporality), + &opentelemetry__proto__metrics__v1__aggregation_temporality__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__histogram__field_indices_by_name[] = { + 1, /* field[1] = aggregation_temporality */ + 0, /* field[0] = data_points */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__histogram__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__histogram__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.Histogram", + "Histogram", + "Opentelemetry__Proto__Metrics__V1__Histogram", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__Histogram), + 2, + opentelemetry__proto__metrics__v1__histogram__field_descriptors, + opentelemetry__proto__metrics__v1__histogram__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__histogram__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__histogram__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__exponential_histogram__field_descriptors[2] = +{ + { + "data_points", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogram, n_data_points), + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogram, data_points), + &opentelemetry__proto__metrics__v1__exponential_histogram_data_point__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "aggregation_temporality", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogram, aggregation_temporality), + &opentelemetry__proto__metrics__v1__aggregation_temporality__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__exponential_histogram__field_indices_by_name[] = { + 1, /* field[1] = aggregation_temporality */ + 0, /* field[0] = data_points */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__exponential_histogram__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__exponential_histogram__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.ExponentialHistogram", + "ExponentialHistogram", + "Opentelemetry__Proto__Metrics__V1__ExponentialHistogram", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogram), + 2, + opentelemetry__proto__metrics__v1__exponential_histogram__field_descriptors, + opentelemetry__proto__metrics__v1__exponential_histogram__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__exponential_histogram__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__exponential_histogram__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__summary__field_descriptors[1] = +{ + { + "data_points", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Summary, n_data_points), + offsetof(Opentelemetry__Proto__Metrics__V1__Summary, data_points), + &opentelemetry__proto__metrics__v1__summary_data_point__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__summary__field_indices_by_name[] = { + 0, /* field[0] = data_points */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__summary__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__summary__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.Summary", + "Summary", + "Opentelemetry__Proto__Metrics__V1__Summary", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__Summary), + 1, + opentelemetry__proto__metrics__v1__summary__field_descriptors, + opentelemetry__proto__metrics__v1__summary__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__summary__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__summary__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__number_data_point__field_descriptors[7] = +{ + { + "start_time_unix_nano", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, start_time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "time_unix_nano", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "as_double", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, value_case), + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, as_double), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "exemplars", + 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, n_exemplars), + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, exemplars), + &opentelemetry__proto__metrics__v1__exemplar__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "as_int", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_SFIXED64, + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, value_case), + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, as_int), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "attributes", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, n_attributes), + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, attributes), + &opentelemetry__proto__common__v1__key_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "flags", + 8, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint, flags), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__number_data_point__field_indices_by_name[] = { + 2, /* field[2] = as_double */ + 4, /* field[4] = as_int */ + 5, /* field[5] = attributes */ + 3, /* field[3] = exemplars */ + 6, /* field[6] = flags */ + 0, /* field[0] = start_time_unix_nano */ + 1, /* field[1] = time_unix_nano */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__number_data_point__number_ranges[1 + 1] = +{ + { 2, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__number_data_point__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.NumberDataPoint", + "NumberDataPoint", + "Opentelemetry__Proto__Metrics__V1__NumberDataPoint", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__NumberDataPoint), + 7, + opentelemetry__proto__metrics__v1__number_data_point__field_descriptors, + opentelemetry__proto__metrics__v1__number_data_point__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__number_data_point__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__number_data_point__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__histogram_data_point__field_descriptors[9] = +{ + { + "start_time_unix_nano", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, start_time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "time_unix_nano", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "count", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "sum", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, sum), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "bucket_counts", + 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_FIXED64, + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, n_bucket_counts), + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, bucket_counts), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "explicit_bounds", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, n_explicit_bounds), + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, explicit_bounds), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "exemplars", + 8, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, n_exemplars), + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, exemplars), + &opentelemetry__proto__metrics__v1__exemplar__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "attributes", + 9, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, n_attributes), + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, attributes), + &opentelemetry__proto__common__v1__key_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "flags", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint, flags), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__histogram_data_point__field_indices_by_name[] = { + 7, /* field[7] = attributes */ + 4, /* field[4] = bucket_counts */ + 2, /* field[2] = count */ + 6, /* field[6] = exemplars */ + 5, /* field[5] = explicit_bounds */ + 8, /* field[8] = flags */ + 0, /* field[0] = start_time_unix_nano */ + 3, /* field[3] = sum */ + 1, /* field[1] = time_unix_nano */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__histogram_data_point__number_ranges[1 + 1] = +{ + { 2, 0 }, + { 0, 9 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__histogram_data_point__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.HistogramDataPoint", + "HistogramDataPoint", + "Opentelemetry__Proto__Metrics__V1__HistogramDataPoint", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__HistogramDataPoint), + 9, + opentelemetry__proto__metrics__v1__histogram_data_point__field_descriptors, + opentelemetry__proto__metrics__v1__histogram_data_point__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__histogram_data_point__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__histogram_data_point__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__field_descriptors[2] = +{ + { + "offset", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_SINT32, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint__Buckets, offset), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "bucket_counts", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT64, + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint__Buckets, n_bucket_counts), + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint__Buckets, bucket_counts), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__field_indices_by_name[] = { + 1, /* field[1] = bucket_counts */ + 0, /* field[0] = offset */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint.Buckets", + "Buckets", + "Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint__Buckets", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint__Buckets), + 2, + opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__field_descriptors, + opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__exponential_histogram_data_point__field_descriptors[11] = +{ + { + "attributes", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, n_attributes), + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, attributes), + &opentelemetry__proto__common__v1__key_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "start_time_unix_nano", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, start_time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "time_unix_nano", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "count", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "sum", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, sum), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "scale", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_SINT32, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, scale), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "zero_count", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, zero_count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "positive", + 8, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, positive), + &opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "negative", + 9, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, negative), + &opentelemetry__proto__metrics__v1__exponential_histogram_data_point__buckets__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "flags", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, flags), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "exemplars", + 11, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, n_exemplars), + offsetof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint, exemplars), + &opentelemetry__proto__metrics__v1__exemplar__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__exponential_histogram_data_point__field_indices_by_name[] = { + 0, /* field[0] = attributes */ + 3, /* field[3] = count */ + 10, /* field[10] = exemplars */ + 9, /* field[9] = flags */ + 8, /* field[8] = negative */ + 7, /* field[7] = positive */ + 5, /* field[5] = scale */ + 1, /* field[1] = start_time_unix_nano */ + 4, /* field[4] = sum */ + 2, /* field[2] = time_unix_nano */ + 6, /* field[6] = zero_count */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__exponential_histogram_data_point__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 11 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__exponential_histogram_data_point__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint", + "ExponentialHistogramDataPoint", + "Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__ExponentialHistogramDataPoint), + 11, + opentelemetry__proto__metrics__v1__exponential_histogram_data_point__field_descriptors, + opentelemetry__proto__metrics__v1__exponential_histogram_data_point__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__exponential_histogram_data_point__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__exponential_histogram_data_point__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__field_descriptors[2] = +{ + { + "quantile", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile, quantile), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile, value), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__field_indices_by_name[] = { + 0, /* field[0] = quantile */ + 1, /* field[1] = value */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.SummaryDataPoint.ValueAtQuantile", + "ValueAtQuantile", + "Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint__ValueAtQuantile), + 2, + opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__field_descriptors, + opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__summary_data_point__field_descriptors[7] = +{ + { + "start_time_unix_nano", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, start_time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "time_unix_nano", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "count", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "sum", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, sum), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "quantile_values", + 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, n_quantile_values), + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, quantile_values), + &opentelemetry__proto__metrics__v1__summary_data_point__value_at_quantile__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "attributes", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, n_attributes), + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, attributes), + &opentelemetry__proto__common__v1__key_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "flags", + 8, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint, flags), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__summary_data_point__field_indices_by_name[] = { + 5, /* field[5] = attributes */ + 2, /* field[2] = count */ + 6, /* field[6] = flags */ + 4, /* field[4] = quantile_values */ + 0, /* field[0] = start_time_unix_nano */ + 3, /* field[3] = sum */ + 1, /* field[1] = time_unix_nano */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__summary_data_point__number_ranges[1 + 1] = +{ + { 2, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__summary_data_point__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.SummaryDataPoint", + "SummaryDataPoint", + "Opentelemetry__Proto__Metrics__V1__SummaryDataPoint", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__SummaryDataPoint), + 7, + opentelemetry__proto__metrics__v1__summary_data_point__field_descriptors, + opentelemetry__proto__metrics__v1__summary_data_point__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__summary_data_point__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__summary_data_point__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor opentelemetry__proto__metrics__v1__exemplar__field_descriptors[6] = +{ + { + "time_unix_nano", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FIXED64, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, time_unix_nano), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "as_double", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, value_case), + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, as_double), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "span_id", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, span_id), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "trace_id", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, trace_id), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "as_int", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_SFIXED64, + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, value_case), + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, as_int), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "filtered_attributes", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, n_filtered_attributes), + offsetof(Opentelemetry__Proto__Metrics__V1__Exemplar, filtered_attributes), + &opentelemetry__proto__common__v1__key_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__metrics__v1__exemplar__field_indices_by_name[] = { + 1, /* field[1] = as_double */ + 4, /* field[4] = as_int */ + 5, /* field[5] = filtered_attributes */ + 2, /* field[2] = span_id */ + 0, /* field[0] = time_unix_nano */ + 3, /* field[3] = trace_id */ +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__exemplar__number_ranges[1 + 1] = +{ + { 2, 0 }, + { 0, 6 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__metrics__v1__exemplar__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.Exemplar", + "Exemplar", + "Opentelemetry__Proto__Metrics__V1__Exemplar", + "opentelemetry.proto.metrics.v1", + sizeof(Opentelemetry__Proto__Metrics__V1__Exemplar), + 6, + opentelemetry__proto__metrics__v1__exemplar__field_descriptors, + opentelemetry__proto__metrics__v1__exemplar__field_indices_by_name, + 1, opentelemetry__proto__metrics__v1__exemplar__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__metrics__v1__exemplar__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue opentelemetry__proto__metrics__v1__aggregation_temporality__enum_values_by_number[3] = +{ + { "AGGREGATION_TEMPORALITY_UNSPECIFIED", "OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_UNSPECIFIED", 0 }, + { "AGGREGATION_TEMPORALITY_DELTA", "OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_DELTA", 1 }, + { "AGGREGATION_TEMPORALITY_CUMULATIVE", "OPENTELEMETRY__PROTO__METRICS__V1__AGGREGATION_TEMPORALITY__AGGREGATION_TEMPORALITY_CUMULATIVE", 2 }, +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__aggregation_temporality__value_ranges[] = { +{0, 0},{0, 3} +}; +static const ProtobufCEnumValueIndex opentelemetry__proto__metrics__v1__aggregation_temporality__enum_values_by_name[3] = +{ + { "AGGREGATION_TEMPORALITY_CUMULATIVE", 2 }, + { "AGGREGATION_TEMPORALITY_DELTA", 1 }, + { "AGGREGATION_TEMPORALITY_UNSPECIFIED", 0 }, +}; +const ProtobufCEnumDescriptor opentelemetry__proto__metrics__v1__aggregation_temporality__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.AggregationTemporality", + "AggregationTemporality", + "Opentelemetry__Proto__Metrics__V1__AggregationTemporality", + "opentelemetry.proto.metrics.v1", + 3, + opentelemetry__proto__metrics__v1__aggregation_temporality__enum_values_by_number, + 3, + opentelemetry__proto__metrics__v1__aggregation_temporality__enum_values_by_name, + 1, + opentelemetry__proto__metrics__v1__aggregation_temporality__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCEnumValue opentelemetry__proto__metrics__v1__data_point_flags__enum_values_by_number[2] = +{ + { "FLAG_NONE", "OPENTELEMETRY__PROTO__METRICS__V1__DATA_POINT_FLAGS__FLAG_NONE", 0 }, + { "FLAG_NO_RECORDED_VALUE", "OPENTELEMETRY__PROTO__METRICS__V1__DATA_POINT_FLAGS__FLAG_NO_RECORDED_VALUE", 1 }, +}; +static const ProtobufCIntRange opentelemetry__proto__metrics__v1__data_point_flags__value_ranges[] = { +{0, 0},{0, 2} +}; +static const ProtobufCEnumValueIndex opentelemetry__proto__metrics__v1__data_point_flags__enum_values_by_name[2] = +{ + { "FLAG_NONE", 0 }, + { "FLAG_NO_RECORDED_VALUE", 1 }, +}; +const ProtobufCEnumDescriptor opentelemetry__proto__metrics__v1__data_point_flags__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "opentelemetry.proto.metrics.v1.DataPointFlags", + "DataPointFlags", + "Opentelemetry__Proto__Metrics__V1__DataPointFlags", + "opentelemetry.proto.metrics.v1", + 2, + opentelemetry__proto__metrics__v1__data_point_flags__enum_values_by_number, + 2, + opentelemetry__proto__metrics__v1__data_point_flags__enum_values_by_name, + 1, + opentelemetry__proto__metrics__v1__data_point_flags__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics_service.pb-c.c b/fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics_service.pb-c.c new file mode 100644 index 00000000..40693015 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics_service.pb-c.c @@ -0,0 +1,189 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: metrics_service.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include <opentelemetry/metrics_service.pb-c.h> + +void opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__init + (Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *message) +{ + static const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest init_value = OPENTELEMETRY__PROTO__COLLECTOR__METRICS__V1__EXPORT_METRICS_SERVICE_REQUEST__INIT; + *message = init_value; +} +size_t opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__get_packed_size + (const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__pack + (const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__pack_to_buffer + (const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest * + opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *) + protobuf_c_message_unpack (&opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__descriptor, + allocator, len, data); +} +void opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__free_unpacked + (Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__init + (Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse *message) +{ + static const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse init_value = OPENTELEMETRY__PROTO__COLLECTOR__METRICS__V1__EXPORT_METRICS_SERVICE_RESPONSE__INIT; + *message = init_value; +} +size_t opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__get_packed_size + (const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__pack + (const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__pack_to_buffer + (const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse * + opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse *) + protobuf_c_message_unpack (&opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__descriptor, + allocator, len, data); +} +void opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__free_unpacked + (Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__field_descriptors[1] = +{ + { + "resource_metrics", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest, n_resource_metrics), + offsetof(Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest, resource_metrics), + &opentelemetry__proto__metrics__v1__resource_metrics__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__field_indices_by_name[] = { + 0, /* field[0] = resource_metrics */ +}; +static const ProtobufCIntRange opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest", + "ExportMetricsServiceRequest", + "Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest", + "opentelemetry.proto.collector.metrics.v1", + sizeof(Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest), + 1, + opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__field_descriptors, + opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__field_indices_by_name, + 1, opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__field_descriptors NULL +#define opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__field_indices_by_name NULL +#define opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__number_ranges NULL +const ProtobufCMessageDescriptor opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse", + "ExportMetricsServiceResponse", + "Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse", + "opentelemetry.proto.collector.metrics.v1", + sizeof(Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse), + 0, + opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__field_descriptors, + opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__field_indices_by_name, + 0, opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCMethodDescriptor opentelemetry__proto__collector__metrics__v1__metrics_service__method_descriptors[1] = +{ + { "Export", &opentelemetry__proto__collector__metrics__v1__export_metrics_service_request__descriptor, &opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__descriptor }, +}; +const unsigned opentelemetry__proto__collector__metrics__v1__metrics_service__method_indices_by_name[] = { + 0 /* Export */ +}; +const ProtobufCServiceDescriptor opentelemetry__proto__collector__metrics__v1__metrics_service__descriptor = +{ + PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.collector.metrics.v1.MetricsService", + "MetricsService", + "Opentelemetry__Proto__Collector__Metrics__V1__MetricsService", + "opentelemetry.proto.collector.metrics.v1", + 1, + opentelemetry__proto__collector__metrics__v1__metrics_service__method_descriptors, + opentelemetry__proto__collector__metrics__v1__metrics_service__method_indices_by_name +}; +void opentelemetry__proto__collector__metrics__v1__metrics_service__export(ProtobufCService *service, + const Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceRequest *input, + Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse_Closure closure, + void *closure_data) +{ + assert(service->descriptor == &opentelemetry__proto__collector__metrics__v1__metrics_service__descriptor); + service->invoke(service, 0, (const ProtobufCMessage *) input, (ProtobufCClosure) closure, closure_data); +} +void opentelemetry__proto__collector__metrics__v1__metrics_service__init (Opentelemetry__Proto__Collector__Metrics__V1__MetricsService_Service *service, + Opentelemetry__Proto__Collector__Metrics__V1__MetricsService_ServiceDestroy destroy) +{ + protobuf_c_service_generated_init (&service->base, + &opentelemetry__proto__collector__metrics__v1__metrics_service__descriptor, + (ProtobufCServiceDestroy) destroy); +} diff --git a/fluent-bit/lib/cmetrics/src/external/opentelemetry_resource.pb-c.c b/fluent-bit/lib/cmetrics/src/external/opentelemetry_resource.pb-c.c new file mode 100644 index 00000000..2efd350a --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/opentelemetry_resource.pb-c.c @@ -0,0 +1,105 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: resource.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include <opentelemetry/resource.pb-c.h> +void opentelemetry__proto__resource__v1__resource__init + (Opentelemetry__Proto__Resource__V1__Resource *message) +{ + static const Opentelemetry__Proto__Resource__V1__Resource init_value = OPENTELEMETRY__PROTO__RESOURCE__V1__RESOURCE__INIT; + *message = init_value; +} +size_t opentelemetry__proto__resource__v1__resource__get_packed_size + (const Opentelemetry__Proto__Resource__V1__Resource *message) +{ + assert(message->base.descriptor == &opentelemetry__proto__resource__v1__resource__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t opentelemetry__proto__resource__v1__resource__pack + (const Opentelemetry__Proto__Resource__V1__Resource *message, + uint8_t *out) +{ + assert(message->base.descriptor == &opentelemetry__proto__resource__v1__resource__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t opentelemetry__proto__resource__v1__resource__pack_to_buffer + (const Opentelemetry__Proto__Resource__V1__Resource *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &opentelemetry__proto__resource__v1__resource__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Opentelemetry__Proto__Resource__V1__Resource * + opentelemetry__proto__resource__v1__resource__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Opentelemetry__Proto__Resource__V1__Resource *) + protobuf_c_message_unpack (&opentelemetry__proto__resource__v1__resource__descriptor, + allocator, len, data); +} +void opentelemetry__proto__resource__v1__resource__free_unpacked + (Opentelemetry__Proto__Resource__V1__Resource *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &opentelemetry__proto__resource__v1__resource__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor opentelemetry__proto__resource__v1__resource__field_descriptors[2] = +{ + { + "attributes", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Opentelemetry__Proto__Resource__V1__Resource, n_attributes), + offsetof(Opentelemetry__Proto__Resource__V1__Resource, attributes), + &opentelemetry__proto__common__v1__key_value__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "dropped_attributes_count", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Opentelemetry__Proto__Resource__V1__Resource, dropped_attributes_count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned opentelemetry__proto__resource__v1__resource__field_indices_by_name[] = { + 0, /* field[0] = attributes */ + 1, /* field[1] = dropped_attributes_count */ +}; +static const ProtobufCIntRange opentelemetry__proto__resource__v1__resource__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor opentelemetry__proto__resource__v1__resource__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "opentelemetry.proto.resource.v1.Resource", + "Resource", + "Opentelemetry__Proto__Resource__V1__Resource", + "opentelemetry.proto.resource.v1", + sizeof(Opentelemetry__Proto__Resource__V1__Resource), + 2, + opentelemetry__proto__resource__v1__resource__field_descriptors, + opentelemetry__proto__resource__v1__resource__field_indices_by_name, + 1, opentelemetry__proto__resource__v1__resource__number_ranges, + (ProtobufCMessageInit) opentelemetry__proto__resource__v1__resource__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/fluent-bit/lib/cmetrics/src/external/protobuf-c.c b/fluent-bit/lib/cmetrics/src/external/protobuf-c.c new file mode 100644 index 00000000..4d1028cd --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/protobuf-c.c @@ -0,0 +1,3667 @@ +/* + * Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * Support library for `protoc-c` generated code. + * + * This file implements the public API used by the code generated + * by `protoc-c`. + * + * \authors Dave Benson and the protobuf-c authors + * + * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. + */ + +/** + * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math + * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64). + * + * \todo Use size_t consistently. + */ + +#include <stdlib.h> /* for malloc, free */ +#include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */ + +#include <prometheus_remote_write/protobuf-c.h> + +#define TRUE 1 +#define FALSE 0 + +#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0) + +/* Workaround for Microsoft compilers. */ +#ifdef _MSC_VER +# define inline __inline +#endif + +/** + * \defgroup internal Internal functions and macros + * + * These are not exported by the library but are useful to developers working + * on `libprotobuf-c` itself. + */ + +/** + * \defgroup macros Utility macros for manipulating structures + * + * Macros and constants used to manipulate the base "classes" generated by + * `protobuf-c`. They also define limits and check correctness. + * + * \ingroup internal + * @{ + */ + +/** The maximum length of a 64-bit integer in varint encoding. */ +#define MAX_UINT64_ENCODED_SIZE 10 + +#ifndef PROTOBUF_C_UNPACK_ERROR +# define PROTOBUF_C_UNPACK_ERROR(...) +#endif + +#if !defined(_WIN32) || !defined(PROTOBUF_C_USE_SHARED_LIB) +const char protobuf_c_empty_string[] = ""; +#endif + +/** + * Internal `ProtobufCMessage` manipulation macro. + * + * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and + * STRUCT_MEMBER_PTR(). + */ +#define STRUCT_MEMBER_P(struct_p, struct_offset) \ + ((void *) ((uint8_t *) (struct_p) + (struct_offset))) + +/** + * Return field in a `ProtobufCMessage` based on offset. + * + * Take a pointer to a `ProtobufCMessage` and find the field at the offset. + * Cast it to the passed type. + */ +#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \ + (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) + +/** + * Return field in a `ProtobufCMessage` based on offset. + * + * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast + * it to a pointer to the passed type. + */ +#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \ + ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) + +/* Assertions for magic numbers. */ + +#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC) + +#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) + +#define ASSERT_IS_MESSAGE(message) \ + ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor) + +#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC) + +/**@}*/ + +/* --- version --- */ + +const char * +protobuf_c_version(void) +{ + return PROTOBUF_C_VERSION; +} + +uint32_t +protobuf_c_version_number(void) +{ + return PROTOBUF_C_VERSION_NUMBER; +} + +/* --- allocator --- */ + +static void * +system_alloc(void *allocator_data, size_t size) +{ + (void)allocator_data; + return malloc(size); +} + +static void +system_free(void *allocator_data, void *data) +{ + (void)allocator_data; + free(data); +} + +static inline void * +do_alloc(ProtobufCAllocator *allocator, size_t size) +{ + return allocator->alloc(allocator->allocator_data, size); +} + +static inline void +do_free(ProtobufCAllocator *allocator, void *data) +{ + if (data != NULL) + allocator->free(allocator->allocator_data, data); +} + +/* + * This allocator uses the system's malloc() and free(). It is the default + * allocator used if NULL is passed as the ProtobufCAllocator to an exported + * function. + */ +static ProtobufCAllocator protobuf_c__allocator = { + .alloc = &system_alloc, + .free = &system_free, + .allocator_data = NULL, +}; + +/* === buffer-simple === */ + +void +protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer, + size_t len, const uint8_t *data) +{ + ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer; + size_t new_len = simp->len + len; + + if (new_len > simp->alloced) { + ProtobufCAllocator *allocator = simp->allocator; + size_t new_alloced = simp->alloced * 2; + uint8_t *new_data; + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + while (new_alloced < new_len) + new_alloced += new_alloced; + new_data = do_alloc(allocator, new_alloced); + if (!new_data) + return; + memcpy(new_data, simp->data, simp->len); + if (simp->must_free_data) + do_free(allocator, simp->data); + else + simp->must_free_data = TRUE; + simp->data = new_data; + simp->alloced = new_alloced; + } + memcpy(simp->data + simp->len, data, len); + simp->len = new_len; +} + +/** + * \defgroup packedsz protobuf_c_message_get_packed_size() implementation + * + * Routines mainly used by protobuf_c_message_get_packed_size(). + * + * \ingroup internal + * @{ + */ + +/** + * Return the number of bytes required to store the tag for the field. Includes + * 3 bits for the wire-type, and a single bit that denotes the end-of-tag. + * + * \param number + * Field tag to encode. + * \return + * Number of bytes required. + */ +static inline size_t +get_tag_size(uint32_t number) +{ + if (number < (1UL << 4)) { + return 1; + } else if (number < (1UL << 11)) { + return 2; + } else if (number < (1UL << 18)) { + return 3; + } else if (number < (1UL << 25)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the number of bytes required to store a variable-length unsigned + * 32-bit integer in base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +uint32_size(uint32_t v) +{ + if (v < (1UL << 7)) { + return 1; + } else if (v < (1UL << 14)) { + return 2; + } else if (v < (1UL << 21)) { + return 3; + } else if (v < (1UL << 28)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the number of bytes required to store a variable-length signed 32-bit + * integer in base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +int32_size(int32_t v) +{ + if (v < 0) { + return 10; + } else if (v < (1L << 7)) { + return 1; + } else if (v < (1L << 14)) { + return 2; + } else if (v < (1L << 21)) { + return 3; + } else if (v < (1L << 28)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed + * integer. + * + * \param v + * Value to encode. + * \return + * ZigZag encoded integer. + */ +static inline uint32_t +zigzag32(int32_t v) +{ + // Note: the right-shift must be arithmetic + // Note: left shift must be unsigned because of overflow + return ((uint32_t)(v) << 1) ^ (uint32_t)(v >> 31); +} + +/** + * Return the number of bytes required to store a signed 32-bit integer, + * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128 + * varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +sint32_size(int32_t v) +{ + return uint32_size(zigzag32(v)); +} + +/** + * Return the number of bytes required to store a 64-bit unsigned integer in + * base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +uint64_size(uint64_t v) +{ + uint32_t upper_v = (uint32_t) (v >> 32); + + if (upper_v == 0) { + return uint32_size((uint32_t) v); + } else if (upper_v < (1UL << 3)) { + return 5; + } else if (upper_v < (1UL << 10)) { + return 6; + } else if (upper_v < (1UL << 17)) { + return 7; + } else if (upper_v < (1UL << 24)) { + return 8; + } else if (upper_v < (1UL << 31)) { + return 9; + } else { + return 10; + } +} + +/** + * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed + * integer. + * + * \param v + * Value to encode. + * \return + * ZigZag encoded integer. + */ +static inline uint64_t +zigzag64(int64_t v) +{ + // Note: the right-shift must be arithmetic + // Note: left shift must be unsigned because of overflow + return ((uint64_t)(v) << 1) ^ (uint64_t)(v >> 63); +} + +/** + * Return the number of bytes required to store a signed 64-bit integer, + * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128 + * varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +sint64_size(int64_t v) +{ + return uint64_size(zigzag64(v)); +} + +/** + * Calculate the serialized size of a single required message field, including + * the space needed by the preceding tag. + * + * \param field + * Field descriptor for member. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +required_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const void *member) +{ + size_t rv = get_tag_size(field->id); + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + return rv + sint32_size(*(const int32_t *) member); + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + return rv + int32_size(*(const int32_t *) member); + case PROTOBUF_C_TYPE_UINT32: + return rv + uint32_size(*(const uint32_t *) member); + case PROTOBUF_C_TYPE_SINT64: + return rv + sint64_size(*(const int64_t *) member); + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + return rv + uint64_size(*(const uint64_t *) member); + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + return rv + 4; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + return rv + 8; + case PROTOBUF_C_TYPE_BOOL: + return rv + 1; + case PROTOBUF_C_TYPE_FLOAT: + return rv + 4; + case PROTOBUF_C_TYPE_DOUBLE: + return rv + 8; + case PROTOBUF_C_TYPE_STRING: { + const char *str = *(char * const *) member; + size_t len = str ? strlen(str) : 0; + return rv + uint32_size(len) + len; + } + case PROTOBUF_C_TYPE_BYTES: { + size_t len = ((const ProtobufCBinaryData *) member)->len; + return rv + uint32_size(len) + len; + } + case PROTOBUF_C_TYPE_MESSAGE: { + const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; + size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0; + return rv + uint32_size(subrv) + subrv; + } + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Calculate the serialized size of a single oneof message field, including + * the space needed by the preceding tag. Returns 0 if the oneof field isn't + * selected or is not set. + * + * \param field + * Field descriptor for member. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_get_packed_size(field, member); +} + +/** + * Calculate the serialized size of a single optional message field, including + * the space needed by the preceding tag. Returns 0 if the optional field isn't + * set. + * + * \param field + * Field descriptor for member. + * \param has + * True if the field exists, false if not. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +optional_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_get_packed_size(field, member); +} + +static protobuf_c_boolean +field_is_zeroish(const ProtobufCFieldDescriptor *field, + const void *member) +{ + protobuf_c_boolean ret = FALSE; + + switch (field->type) { + case PROTOBUF_C_TYPE_BOOL: + ret = (0 == *(const protobuf_c_boolean *) member); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + ret = (0 == *(const uint32_t *) member); + break; + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + ret = (0 == *(const uint64_t *) member); + break; + case PROTOBUF_C_TYPE_FLOAT: + ret = (0 == *(const float *) member); + break; + case PROTOBUF_C_TYPE_DOUBLE: + ret = (0 == *(const double *) member); + break; + case PROTOBUF_C_TYPE_STRING: + ret = (NULL == *(const char * const *) member) || + ('\0' == **(const char * const *) member); + break; + case PROTOBUF_C_TYPE_BYTES: + case PROTOBUF_C_TYPE_MESSAGE: + ret = (NULL == *(const void * const *) member); + break; + default: + ret = TRUE; + break; + } + + return ret; +} + +/** + * Calculate the serialized size of a single unlabeled message field, including + * the space needed by the preceding tag. Returns 0 if the field isn't set or + * if it is set to a "zeroish" value (null pointer or 0 for numerical values). + * Unlabeled fields are supported only in proto3. + * + * \param field + * Field descriptor for member. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const void *member) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_get_packed_size(field, member); +} + +/** + * Calculate the serialized size of repeated message fields, which may consist + * of any number of values (including 0). Includes the space needed by the + * preceding tags (as needed). + * + * \param field + * Field descriptor for member. + * \param count + * Number of repeated field members. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field, + size_t count, const void *member) +{ + size_t header_size; + size_t rv = 0; + unsigned i; + void *array = *(void * const *) member; + + if (count == 0) + return 0; + header_size = get_tag_size(field->id); + if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) + header_size *= count; + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + for (i = 0; i < count; i++) + rv += sint32_size(((int32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + for (i = 0; i < count; i++) + rv += int32_size(((int32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_UINT32: + for (i = 0; i < count; i++) + rv += uint32_size(((uint32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_SINT64: + for (i = 0; i < count; i++) + rv += sint64_size(((int64_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + for (i = 0; i < count; i++) + rv += uint64_size(((uint64_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + rv += 4 * count; + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + rv += 8 * count; + break; + case PROTOBUF_C_TYPE_BOOL: + rv += count; + break; + case PROTOBUF_C_TYPE_STRING: + for (i = 0; i < count; i++) { + size_t len = strlen(((char **) array)[i]); + rv += uint32_size(len) + len; + } + break; + case PROTOBUF_C_TYPE_BYTES: + for (i = 0; i < count; i++) { + size_t len = ((ProtobufCBinaryData *) array)[i].len; + rv += uint32_size(len) + len; + } + break; + case PROTOBUF_C_TYPE_MESSAGE: + for (i = 0; i < count; i++) { + size_t len = protobuf_c_message_get_packed_size( + ((ProtobufCMessage **) array)[i]); + rv += uint32_size(len) + len; + } + break; + } + + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) + header_size += uint32_size(rv); + return header_size + rv; +} + +/** + * Calculate the serialized size of an unknown field, i.e. one that is passed + * through mostly uninterpreted. This is required for forward compatibility if + * new fields are added to the message descriptor. + * + * \param field + * Unknown field type. + * \return + * Number of bytes required. + */ +static inline size_t +unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field) +{ + return get_tag_size(field->tag) + field->len; +} + +/**@}*/ + +/* + * Calculate the serialized size of the message. + */ +size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = + ((const char *) message) + field->offset; + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_get_packed_size(field, member); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_get_packed_size( + field, + *(const uint32_t *) qmember, + member + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_get_packed_size( + field, + *(protobuf_c_boolean *) qmember, + member + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_get_packed_size( + field, + member + ); + } else { + rv += repeated_field_get_packed_size( + field, + *(const size_t *) qmember, + member + ); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_get_packed_size(&message->unknown_fields[i]); + return rv; +} + +/** + * \defgroup pack protobuf_c_message_pack() implementation + * + * Routines mainly used by protobuf_c_message_pack(). + * + * \ingroup internal + * @{ + */ + +/** + * Pack an unsigned 32-bit integer in base-128 varint encoding and return the + * number of bytes written, which must be 5 or less. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +uint32_pack(uint32_t value, uint8_t *out) +{ + unsigned rv = 0; + + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + } + } + } + } + /* assert: value<128 */ + out[rv++] = value; + return rv; +} + +/** + * Pack a signed 32-bit integer and return the number of bytes written. + * Negative numbers are encoded as two's complement 64-bit integers. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +int32_pack(int32_t value, uint8_t *out) +{ + if (value < 0) { + out[0] = value | 0x80; + out[1] = (value >> 7) | 0x80; + out[2] = (value >> 14) | 0x80; + out[3] = (value >> 21) | 0x80; + out[4] = (value >> 28) | 0x80; + out[5] = out[6] = out[7] = out[8] = 0xff; + out[9] = 0x01; + return 10; + } else { + return uint32_pack(value, out); + } +} + +/** + * Pack a signed 32-bit integer using ZigZag encoding and return the number of + * bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +sint32_pack(int32_t value, uint8_t *out) +{ + return uint32_pack(zigzag32(value), out); +} + +/** + * Pack a 64-bit unsigned integer using base-128 varint encoding and return the + * number of bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +uint64_pack(uint64_t value, uint8_t *out) +{ + uint32_t hi = (uint32_t) (value >> 32); + uint32_t lo = (uint32_t) value; + unsigned rv; + + if (hi == 0) + return uint32_pack((uint32_t) lo, out); + out[0] = (lo) | 0x80; + out[1] = (lo >> 7) | 0x80; + out[2] = (lo >> 14) | 0x80; + out[3] = (lo >> 21) | 0x80; + if (hi < 8) { + out[4] = (hi << 4) | (lo >> 28); + return 5; + } else { + out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80; + hi >>= 3; + } + rv = 5; + while (hi >= 128) { + out[rv++] = hi | 0x80; + hi >>= 7; + } + out[rv++] = hi; + return rv; +} + +/** + * Pack a 64-bit signed integer in ZigZag encoding and return the number of + * bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +sint64_pack(int64_t value, uint8_t *out) +{ + return uint64_pack(zigzag64(value), out); +} + +/** + * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire + * types fixed32, sfixed32, float. Similar to "htole32". + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +fixed32_pack(uint32_t value, void *out) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, &value, 4); +#else + uint8_t *buf = out; + + buf[0] = value; + buf[1] = value >> 8; + buf[2] = value >> 16; + buf[3] = value >> 24; +#endif + return 4; +} + +/** + * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire + * types fixed64, sfixed64, double. Similar to "htole64". + * + * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit + * version would be appreciated, plus a way to decide to use 64-bit math where + * convenient. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +fixed64_pack(uint64_t value, void *out) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, &value, 8); +#else + fixed32_pack(value, out); + fixed32_pack(value >> 32, ((char *) out) + 4); +#endif + return 8; +} + +/** + * Pack a boolean value as an integer and return the number of bytes written. + * + * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c + * that is idiomatic C++ in some STL implementations. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +boolean_pack(protobuf_c_boolean value, uint8_t *out) +{ + *out = value ? TRUE : FALSE; + return 1; +} + +/** + * Pack a NUL-terminated C string and return the number of bytes written. The + * output includes a length delimiter. + * + * The NULL pointer is treated as an empty string. This isn't really necessary, + * but it allows people to leave required strings blank. (See Issue #13 in the + * bug tracker for a little more explanation). + * + * \param str + * String to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +string_pack(const char *str, uint8_t *out) +{ + if (str == NULL) { + out[0] = 0; + return 1; + } else { + size_t len = strlen(str); + size_t rv = uint32_pack(len, out); + memcpy(out + rv, str, len); + return rv + len; + } +} + +/** + * Pack a ProtobufCBinaryData and return the number of bytes written. The output + * includes a length delimiter. + * + * \param bd + * ProtobufCBinaryData to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out) +{ + size_t len = bd->len; + size_t rv = uint32_pack(len, out); + memcpy(out + rv, bd->data, len); + return rv + len; +} + +/** + * Pack a ProtobufCMessage and return the number of bytes written. The output + * includes a length delimiter. + * + * \param message + * ProtobufCMessage object to pack. + * \param[out] out + * Packed message. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out) +{ + if (message == NULL) { + out[0] = 0; + return 1; + } else { + size_t rv = protobuf_c_message_pack(message, out + 1); + uint32_t rv_packed_size = uint32_size(rv); + if (rv_packed_size != 1) + memmove(out + rv_packed_size, out + 1, rv); + return uint32_pack(rv, out) + rv; + } +} + +/** + * Pack a field tag. + * + * Wire-type will be added in required_field_pack(). + * + * \todo Just call uint64_pack on 64-bit platforms. + * + * \param id + * Tag value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +tag_pack(uint32_t id, uint8_t *out) +{ + if (id < (1UL << (32 - 3))) + return uint32_pack(id << 3, out); + else + return uint64_pack(((uint64_t) id) << 3, out); +} + +/** + * Pack a required field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +required_field_pack(const ProtobufCFieldDescriptor *field, + const void *member, uint8_t *out) +{ + size_t rv = tag_pack(field->id, out); + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + sint32_pack(*(const int32_t *) member, out + rv); + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + int32_pack(*(const int32_t *) member, out + rv); + case PROTOBUF_C_TYPE_UINT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + uint32_pack(*(const uint32_t *) member, out + rv); + case PROTOBUF_C_TYPE_SINT64: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + sint64_pack(*(const int64_t *) member, out + rv); + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + uint64_pack(*(const uint64_t *) member, out + rv); + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; + return rv + fixed32_pack(*(const uint32_t *) member, out + rv); + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; + return rv + fixed64_pack(*(const uint64_t *) member, out + rv); + case PROTOBUF_C_TYPE_BOOL: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv); + case PROTOBUF_C_TYPE_STRING: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + string_pack(*(char *const *) member, out + rv); + case PROTOBUF_C_TYPE_BYTES: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv); + case PROTOBUF_C_TYPE_MESSAGE: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv); + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Pack a oneof field and return the number of bytes written. Only packs the + * field that is selected by the case enum. + * + * \param field + * Field descriptor. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +oneof_field_pack(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member, uint8_t *out) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_pack(field, member, out); +} + +/** + * Pack an optional field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param has + * Whether the field is set. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +optional_field_pack(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member, uint8_t *out) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_pack(field, member, out); +} + +/** + * Pack an unlabeled field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +unlabeled_field_pack(const ProtobufCFieldDescriptor *field, + const void *member, uint8_t *out) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_pack(field, member, out); +} + +/** + * Given a field type, return the in-memory size. + * + * \todo Implement as a table lookup. + * + * \param type + * Field type. + * \return + * Size of the field. + */ +static inline size_t +sizeof_elt_in_repeated_array(ProtobufCType type) +{ + switch (type) { + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + case PROTOBUF_C_TYPE_ENUM: + return 4; + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + return 8; + case PROTOBUF_C_TYPE_BOOL: + return sizeof(protobuf_c_boolean); + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_MESSAGE: + return sizeof(void *); + case PROTOBUF_C_TYPE_BYTES: + return sizeof(ProtobufCBinaryData); + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Pack an array of 32-bit quantities. + * + * \param[out] out + * Destination. + * \param[in] in + * Source. + * \param[in] n + * Number of elements in the source array. + */ +static void +copy_to_little_endian_32(void *out, const void *in, const unsigned n) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, in, n * 4); +#else + unsigned i; + const uint32_t *ini = in; + for (i = 0; i < n; i++) + fixed32_pack(ini[i], (uint32_t *) out + i); +#endif +} + +/** + * Pack an array of 64-bit quantities. + * + * \param[out] out + * Destination. + * \param[in] in + * Source. + * \param[in] n + * Number of elements in the source array. + */ +static void +copy_to_little_endian_64(void *out, const void *in, const unsigned n) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, in, n * 8); +#else + unsigned i; + const uint64_t *ini = in; + for (i = 0; i < n; i++) + fixed64_pack(ini[i], (uint64_t *) out + i); +#endif +} + +/** + * Get the minimum number of bytes required to pack a field value of a + * particular type. + * + * \param type + * Field type. + * \return + * Number of bytes. + */ +static unsigned +get_type_min_size(ProtobufCType type) +{ + if (type == PROTOBUF_C_TYPE_SFIXED32 || + type == PROTOBUF_C_TYPE_FIXED32 || + type == PROTOBUF_C_TYPE_FLOAT) + { + return 4; + } + if (type == PROTOBUF_C_TYPE_SFIXED64 || + type == PROTOBUF_C_TYPE_FIXED64 || + type == PROTOBUF_C_TYPE_DOUBLE) + { + return 8; + } + return 1; +} + +/** + * Packs the elements of a repeated field and returns the serialised field and + * its length. + * + * \param field + * Field descriptor. + * \param count + * Number of elements in the repeated field array. + * \param member + * Pointer to the elements for this repeated field. + * \param[out] out + * Serialised representation of the repeated field. + * \return + * Number of bytes serialised to `out`. + */ +static size_t +repeated_field_pack(const ProtobufCFieldDescriptor *field, + size_t count, const void *member, uint8_t *out) +{ + void *array = *(void * const *) member; + unsigned i; + + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { + unsigned header_len; + unsigned len_start; + unsigned min_length; + unsigned payload_len; + unsigned length_size_min; + unsigned actual_length_size; + uint8_t *payload_at; + + if (count == 0) + return 0; + header_len = tag_pack(field->id, out); + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + len_start = header_len; + min_length = get_type_min_size(field->type) * count; + length_size_min = uint32_size(min_length); + header_len += length_size_min; + payload_at = out + header_len; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + copy_to_little_endian_32(payload_at, array, count); + payload_at += count * 4; + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + copy_to_little_endian_64(payload_at, array, count); + payload_at += count * 8; + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + payload_at += int32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_SINT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + payload_at += sint32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_SINT64: { + const int64_t *arr = (const int64_t *) array; + for (i = 0; i < count; i++) + payload_at += sint64_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_UINT32: { + const uint32_t *arr = (const uint32_t *) array; + for (i = 0; i < count; i++) + payload_at += uint32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: { + const uint64_t *arr = (const uint64_t *) array; + for (i = 0; i < count; i++) + payload_at += uint64_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_BOOL: { + const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array; + for (i = 0; i < count; i++) + payload_at += boolean_pack(arr[i], payload_at); + break; + } + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + + payload_len = payload_at - (out + header_len); + actual_length_size = uint32_size(payload_len); + if (length_size_min != actual_length_size) { + assert(actual_length_size == length_size_min + 1); + memmove(out + header_len + 1, out + header_len, + payload_len); + header_len++; + } + uint32_pack(payload_len, out + len_start); + return header_len + payload_len; + } else { + /* not "packed" cased */ + /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ + size_t rv = 0; + unsigned siz = sizeof_elt_in_repeated_array(field->type); + + for (i = 0; i < count; i++) { + rv += required_field_pack(field, array, out + rv); + array = (char *)array + siz; + } + return rv; + } +} + +static size_t +unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out) +{ + size_t rv = tag_pack(field->tag, out); + out[0] |= field->wire_type; + memcpy(out + rv, field->data, field->len); + return rv + field->len; +} + +/**@}*/ + +size_t +protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = ((const char *) message) + field->offset; + + /* + * It doesn't hurt to compute qmember (a pointer to the + * quantifier field of the structure), but the pointer is only + * valid if the field is: + * - a repeated field, or + * - a field that is part of a oneof + * - an optional field that isn't a pointer type + * (Meaning: not a message or a string). + */ + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_pack(field, member, out + rv); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_pack( + field, + *(const uint32_t *) qmember, + member, + out + rv + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_pack( + field, + *(const protobuf_c_boolean *) qmember, + member, + out + rv + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_pack(field, member, out + rv); + } else { + rv += repeated_field_pack(field, *(const size_t *) qmember, + member, out + rv); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_pack(&message->unknown_fields[i], out + rv); + return rv; +} + +/** + * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation + * + * Routines mainly used by protobuf_c_message_pack_to_buffer(). + * + * \ingroup internal + * @{ + */ + +/** + * Pack a required field to a virtual buffer. + * + * \param field + * Field descriptor. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes packed. + */ +static size_t +required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const void *member, ProtobufCBuffer *buffer) +{ + size_t rv; + uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; + + rv = tag_pack(field->id, scratch); + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += sint32_pack(*(const int32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += int32_pack(*(const int32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_UINT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += uint32_pack(*(const uint32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SINT64: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += sint64_pack(*(const int64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += uint64_pack(*(const uint64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; + rv += fixed32_pack(*(const uint32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; + rv += fixed64_pack(*(const uint64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_BOOL: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_STRING: { + const char *str = *(char *const *) member; + size_t sublen = str ? strlen(str) : 0; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, (const uint8_t *) str); + rv += sublen; + break; + } + case PROTOBUF_C_TYPE_BYTES: { + const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member); + size_t sublen = bd->len; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, bd->data); + rv += sublen; + break; + } + case PROTOBUF_C_TYPE_MESSAGE: { + const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + if (msg == NULL) { + rv += uint32_pack(0, scratch + rv); + buffer->append(buffer, rv, scratch); + } else { + size_t sublen = protobuf_c_message_get_packed_size(msg); + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + protobuf_c_message_pack_to_buffer(msg, buffer); + rv += sublen; + } + break; + } + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; +} + +/** + * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum. + * + * \param field + * Field descriptor. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member, ProtobufCBuffer *buffer) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void *const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Pack an optional field to a buffer. + * + * \param field + * Field descriptor. + * \param has + * Whether the field is set. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member, ProtobufCBuffer *buffer) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void *const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Pack an unlabeled field to a buffer. + * + * \param field + * Field descriptor. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const void *member, ProtobufCBuffer *buffer) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Get the packed size of an array of same field type. + * + * \param field + * Field descriptor. + * \param count + * Number of elements of this type. + * \param array + * The elements to get the size of. + * \return + * Number of bytes required. + */ +static size_t +get_packed_payload_length(const ProtobufCFieldDescriptor *field, + unsigned count, const void *array) +{ + unsigned rv = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + return count * 4; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + return count * 8; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + rv += int32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_SINT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + rv += sint32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_UINT32: { + const uint32_t *arr = (const uint32_t *) array; + for (i = 0; i < count; i++) + rv += uint32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_SINT64: { + const int64_t *arr = (const int64_t *) array; + for (i = 0; i < count; i++) + rv += sint64_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: { + const uint64_t *arr = (const uint64_t *) array; + for (i = 0; i < count; i++) + rv += uint64_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_BOOL: + return count; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; +} + +/** + * Pack an array of same field type to a virtual buffer. + * + * \param field + * Field descriptor. + * \param count + * Number of elements of this type. + * \param array + * The elements to get the size of. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes packed. + */ +static size_t +pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field, + unsigned count, const void *array, + ProtobufCBuffer *buffer) +{ + uint8_t scratch[16]; + size_t rv = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: +#if !defined(WORDS_BIGENDIAN) + rv = count * 4; + goto no_packing_needed; +#else + for (i = 0; i < count; i++) { + unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; +#endif + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: +#if !defined(WORDS_BIGENDIAN) + rv = count * 8; + goto no_packing_needed; +#else + for (i = 0; i < count; i++) { + unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; +#endif + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + for (i = 0; i < count; i++) { + unsigned len = int32_pack(((int32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_SINT32: + for (i = 0; i < count; i++) { + unsigned len = sint32_pack(((int32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_UINT32: + for (i = 0; i < count; i++) { + unsigned len = uint32_pack(((uint32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_SINT64: + for (i = 0; i < count; i++) { + unsigned len = sint64_pack(((int64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + for (i = 0; i < count; i++) { + unsigned len = uint64_pack(((uint64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_BOOL: + for (i = 0; i < count; i++) { + unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + return count; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; + +#if !defined(WORDS_BIGENDIAN) +no_packing_needed: + buffer->append(buffer, rv, array); + return rv; +#endif +} + +static size_t +repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + unsigned count, const void *member, + ProtobufCBuffer *buffer) +{ + char *array = *(char * const *) member; + + if (count == 0) + return 0; + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { + uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; + size_t rv = tag_pack(field->id, scratch); + size_t payload_len = get_packed_payload_length(field, count, array); + size_t tmp; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(payload_len, scratch + rv); + buffer->append(buffer, rv, scratch); + tmp = pack_buffer_packed_payload(field, count, array, buffer); + assert(tmp == payload_len); + return rv + payload_len; + } else { + size_t siz; + unsigned i; + /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ + unsigned rv = 0; + + siz = sizeof_elt_in_repeated_array(field->type); + for (i = 0; i < count; i++) { + rv += required_field_pack_to_buffer(field, array, buffer); + array += siz; + } + return rv; + } +} + +static size_t +unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field, + ProtobufCBuffer *buffer) +{ + uint8_t header[MAX_UINT64_ENCODED_SIZE]; + size_t rv = tag_pack(field->tag, header); + + header[0] |= field->wire_type; + buffer->append(buffer, rv, header); + buffer->append(buffer, field->len, field->data); + return rv + field->len; +} + +/**@}*/ + +size_t +protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message, + ProtobufCBuffer *buffer) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = + ((const char *) message) + field->offset; + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_pack_to_buffer(field, member, buffer); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_pack_to_buffer( + field, + *(const uint32_t *) qmember, + member, + buffer + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_pack_to_buffer( + field, + *(const protobuf_c_boolean *) qmember, + member, + buffer + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_pack_to_buffer( + field, + member, + buffer + ); + } else { + rv += repeated_field_pack_to_buffer( + field, + *(const size_t *) qmember, + member, + buffer + ); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer); + + return rv; +} + +/** + * \defgroup unpack unpacking implementation + * + * Routines mainly used by the unpacking functions. + * + * \ingroup internal + * @{ + */ + +static inline int +int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value) +{ + unsigned n; + unsigned start; + + if (n_ranges == 0) + return -1; + start = 0; + n = n_ranges; + while (n > 1) { + unsigned mid = start + n / 2; + + if (value < ranges[mid].start_value) { + n = mid - start; + } else if (value >= ranges[mid].start_value + + (int) (ranges[mid + 1].orig_index - + ranges[mid].orig_index)) + { + unsigned new_start = mid + 1; + n = start + n - new_start; + start = new_start; + } else + return (value - ranges[mid].start_value) + + ranges[mid].orig_index; + } + if (n > 0) { + unsigned start_orig_index = ranges[start].orig_index; + unsigned range_size = + ranges[start + 1].orig_index - start_orig_index; + + if (ranges[start].start_value <= value && + value < (int) (ranges[start].start_value + range_size)) + { + return (value - ranges[start].start_value) + + start_orig_index; + } + } + return -1; +} + +static size_t +parse_tag_and_wiretype(size_t len, + const uint8_t *data, + uint32_t *tag_out, + uint8_t *wiretype_out) +{ + unsigned max_rv = len > 5 ? 5 : len; + uint32_t tag = (data[0] & 0x7f) >> 3; + unsigned shift = 4; + unsigned rv; + + /* 0 is not a valid tag value */ + if ((data[0] & 0xf8) == 0) { + return 0; + } + + *wiretype_out = data[0] & 7; + if ((data[0] & 0x80) == 0) { + *tag_out = tag; + return 1; + } + for (rv = 1; rv < max_rv; rv++) { + if (data[rv] & 0x80) { + tag |= (data[rv] & 0x7f) << shift; + shift += 7; + } else { + tag |= data[rv] << shift; + *tag_out = tag; + return rv + 1; + } + } + return 0; /* error: bad header */ +} + +/* sizeof(ScannedMember) must be <= (1UL<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */ +#define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5 +typedef struct ScannedMember ScannedMember; +/** Field as it's being read. */ +struct ScannedMember { + uint32_t tag; /**< Field tag. */ + uint8_t wire_type; /**< Field type. */ + uint8_t length_prefix_len; /**< Prefix length. */ + const ProtobufCFieldDescriptor *field; /**< Field descriptor. */ + size_t len; /**< Field length. */ + const uint8_t *data; /**< Pointer to field data. */ +}; + +static inline size_t +scan_length_prefixed_data(size_t len, const uint8_t *data, + size_t *prefix_len_out) +{ + unsigned hdr_max = len < 5 ? len : 5; + unsigned hdr_len; + size_t val = 0; + unsigned i; + unsigned shift = 0; + + for (i = 0; i < hdr_max; i++) { + val |= ((size_t)data[i] & 0x7f) << shift; + shift += 7; + if ((data[i] & 0x80) == 0) + break; + } + if (i == hdr_max) { + PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data"); + return 0; + } + hdr_len = i + 1; + *prefix_len_out = hdr_len; + if (val > INT_MAX) { + // Protobuf messages should always be less than 2 GiB in size. + // We also want to return early here so that hdr_len + val does + // not overflow on 32-bit systems. + PROTOBUF_C_UNPACK_ERROR("length prefix of %lu is too large", + (unsigned long int)val); + return 0; + } + if (hdr_len + val > len) { + PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %lu", + (unsigned long int)val); + return 0; + } + return hdr_len + val; +} + +static size_t +max_b128_numbers(size_t len, const uint8_t *data) +{ + size_t rv = 0; + while (len--) + if ((*data++ & 0x80) == 0) + ++rv; + return rv; +} + +/**@}*/ + +/** + * Merge earlier message into a latter message. + * + * For numeric types and strings, if the same value appears multiple + * times, the parser accepts the last value it sees. For embedded + * message fields, the parser merges multiple instances of the same + * field. That is, all singular scalar fields in the latter instance + * replace those in the former, singular embedded messages are merged, + * and repeated fields are concatenated. + * + * The earlier message should be freed after calling this function, as + * some of its fields may have been reused and changed to their default + * values during the merge. + */ +static protobuf_c_boolean +merge_messages(ProtobufCMessage *earlier_msg, + ProtobufCMessage *latter_msg, + ProtobufCAllocator *allocator) +{ + unsigned i; + const ProtobufCFieldDescriptor *fields = + latter_msg->descriptor->fields; + for (i = 0; i < latter_msg->descriptor->n_fields; i++) { + if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) { + size_t *n_earlier = + STRUCT_MEMBER_PTR(size_t, earlier_msg, + fields[i].quantifier_offset); + uint8_t **p_earlier = + STRUCT_MEMBER_PTR(uint8_t *, earlier_msg, + fields[i].offset); + size_t *n_latter = + STRUCT_MEMBER_PTR(size_t, latter_msg, + fields[i].quantifier_offset); + uint8_t **p_latter = + STRUCT_MEMBER_PTR(uint8_t *, latter_msg, + fields[i].offset); + + if (*n_earlier > 0) { + if (*n_latter > 0) { + /* Concatenate the repeated field */ + size_t el_size = + sizeof_elt_in_repeated_array(fields[i].type); + uint8_t *new_field; + + new_field = do_alloc(allocator, + (*n_earlier + *n_latter) * el_size); + if (!new_field) + return FALSE; + + memcpy(new_field, *p_earlier, + *n_earlier * el_size); + memcpy(new_field + + *n_earlier * el_size, + *p_latter, + *n_latter * el_size); + + do_free(allocator, *p_latter); + do_free(allocator, *p_earlier); + *p_latter = new_field; + *n_latter = *n_earlier + *n_latter; + } else { + /* Zero copy the repeated field from the earlier message */ + *n_latter = *n_earlier; + *p_latter = *p_earlier; + } + /* Make sure the field does not get double freed */ + *n_earlier = 0; + *p_earlier = 0; + } + } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL || + fields[i].label == PROTOBUF_C_LABEL_NONE) { + const ProtobufCFieldDescriptor *field; + uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t, + earlier_msg, + fields[i]. + quantifier_offset); + uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t, + latter_msg, + fields[i]. + quantifier_offset); + protobuf_c_boolean need_to_merge = FALSE; + void *earlier_elem; + void *latter_elem; + const void *def_val; + + if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) { + if (*latter_case_p == 0) { + /* lookup correct oneof field */ + int field_index = + int_range_lookup( + latter_msg->descriptor + ->n_field_ranges, + latter_msg->descriptor + ->field_ranges, + *earlier_case_p); + if (field_index < 0) + return FALSE; + field = latter_msg->descriptor->fields + + field_index; + } else { + /* Oneof is present in the latter message, move on */ + continue; + } + } else { + field = &fields[i]; + } + + earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset); + latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset); + def_val = field->default_value; + + switch (field->type) { + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem; + ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem; + if (em != NULL) { + if (lm != NULL) { + if (!merge_messages(em, lm, allocator)) + return FALSE; + /* Already merged */ + need_to_merge = FALSE; + } else { + /* Zero copy the message */ + need_to_merge = TRUE; + } + } + break; + } + case PROTOBUF_C_TYPE_BYTES: { + uint8_t *e_data = + ((ProtobufCBinaryData *) earlier_elem)->data; + uint8_t *l_data = + ((ProtobufCBinaryData *) latter_elem)->data; + const ProtobufCBinaryData *d_bd = + (ProtobufCBinaryData *) def_val; + + need_to_merge = + (e_data != NULL && + (d_bd == NULL || + e_data != d_bd->data)) && + (l_data == NULL || + (d_bd != NULL && + l_data == d_bd->data)); + break; + } + case PROTOBUF_C_TYPE_STRING: { + char *e_str = *(char **) earlier_elem; + char *l_str = *(char **) latter_elem; + const char *d_str = def_val; + + need_to_merge = e_str != d_str && l_str == d_str; + break; + } + default: { + /* Could be has field or case enum, the logic is + * equivalent, since 0 (FALSE) means not set for + * oneof */ + need_to_merge = (*earlier_case_p != 0) && + (*latter_case_p == 0); + break; + } + } + + if (need_to_merge) { + size_t el_size = + sizeof_elt_in_repeated_array(field->type); + memcpy(latter_elem, earlier_elem, el_size); + /* + * Reset the element from the old message to 0 + * to make sure earlier message deallocation + * doesn't corrupt zero-copied data in the new + * message, earlier message will be freed after + * this function is called anyway + */ + memset(earlier_elem, 0, el_size); + + if (field->quantifier_offset != 0) { + /* Set the has field or the case enum, + * if applicable */ + *latter_case_p = *earlier_case_p; + *earlier_case_p = 0; + } + } + } + } + return TRUE; +} + +/** + * Count packed elements. + * + * Given a raw slab of packed-repeated values, determine the number of + * elements. This function detects certain kinds of errors but not + * others; the remaining error checking is done by + * parse_packed_repeated_member(). + */ +static protobuf_c_boolean +count_packed_elements(ProtobufCType type, + size_t len, const uint8_t *data, size_t *count_out) +{ + switch (type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + if (len % 4 != 0) { + PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types"); + return FALSE; + } + *count_out = len / 4; + return TRUE; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + if (len % 8 != 0) { + PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types"); + return FALSE; + } + *count_out = len / 8; + return TRUE; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_UINT64: + *count_out = max_b128_numbers(len, data); + return TRUE; + case PROTOBUF_C_TYPE_BOOL: + *count_out = len; + return TRUE; + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_BYTES: + case PROTOBUF_C_TYPE_MESSAGE: + default: + PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type); + return FALSE; + } +} + +static inline uint32_t +parse_uint32(unsigned len, const uint8_t *data) +{ + uint32_t rv = data[0] & 0x7f; + if (len > 1) { + rv |= ((uint32_t) (data[1] & 0x7f) << 7); + if (len > 2) { + rv |= ((uint32_t) (data[2] & 0x7f) << 14); + if (len > 3) { + rv |= ((uint32_t) (data[3] & 0x7f) << 21); + if (len > 4) + rv |= ((uint32_t) (data[4]) << 28); + } + } + } + return rv; +} + +static inline uint32_t +parse_int32(unsigned len, const uint8_t *data) +{ + return parse_uint32(len, data); +} + +static inline int32_t +unzigzag32(uint32_t v) +{ + // Note: Using unsigned types prevents undefined behavior + return (int32_t)((v >> 1) ^ (~(v & 1) + 1)); +} + +static inline uint32_t +parse_fixed_uint32(const uint8_t *data) +{ +#if !defined(WORDS_BIGENDIAN) + uint32_t t; + memcpy(&t, data, 4); + return t; +#else + return data[0] | + ((uint32_t) (data[1]) << 8) | + ((uint32_t) (data[2]) << 16) | + ((uint32_t) (data[3]) << 24); +#endif +} + +static uint64_t +parse_uint64(unsigned len, const uint8_t *data) +{ + unsigned shift, i; + uint64_t rv; + + if (len < 5) + return parse_uint32(len, data); + rv = ((uint64_t) (data[0] & 0x7f)) | + ((uint64_t) (data[1] & 0x7f) << 7) | + ((uint64_t) (data[2] & 0x7f) << 14) | + ((uint64_t) (data[3] & 0x7f) << 21); + shift = 28; + for (i = 4; i < len; i++) { + rv |= (((uint64_t) (data[i] & 0x7f)) << shift); + shift += 7; + } + return rv; +} + +static inline int64_t +unzigzag64(uint64_t v) +{ + // Note: Using unsigned types prevents undefined behavior + return (int64_t)((v >> 1) ^ (~(v & 1) + 1)); +} + +static inline uint64_t +parse_fixed_uint64(const uint8_t *data) +{ +#if !defined(WORDS_BIGENDIAN) + uint64_t t; + memcpy(&t, data, 8); + return t; +#else + return (uint64_t) parse_fixed_uint32(data) | + (((uint64_t) parse_fixed_uint32(data + 4)) << 32); +#endif +} + +static protobuf_c_boolean +parse_boolean(unsigned len, const uint8_t *data) +{ + unsigned i; + for (i = 0; i < len; i++) + if (data[i] & 0x7f) + return TRUE; + return FALSE; +} + +static protobuf_c_boolean +parse_required_member(ScannedMember *scanned_member, + void *member, + ProtobufCAllocator *allocator, + protobuf_c_boolean maybe_clear) +{ + unsigned len = scanned_member->len; + const uint8_t *data = scanned_member->data; + uint8_t wire_type = scanned_member->wire_type; + + switch (scanned_member->field->type) { + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int32_t *) member = parse_int32(len, data); + return TRUE; + case PROTOBUF_C_TYPE_UINT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(uint32_t *) member = parse_uint32(len, data); + return TRUE; + case PROTOBUF_C_TYPE_SINT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int32_t *) member = unzigzag32(parse_uint32(len, data)); + return TRUE; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT) + return FALSE; + *(uint32_t *) member = parse_fixed_uint32(data); + return TRUE; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(uint64_t *) member = parse_uint64(len, data); + return TRUE; + case PROTOBUF_C_TYPE_SINT64: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int64_t *) member = unzigzag64(parse_uint64(len, data)); + return TRUE; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT) + return FALSE; + *(uint64_t *) member = parse_fixed_uint64(data); + return TRUE; + case PROTOBUF_C_TYPE_BOOL: + *(protobuf_c_boolean *) member = parse_boolean(len, data); + return TRUE; + case PROTOBUF_C_TYPE_STRING: { + char **pstr = member; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + if (maybe_clear && *pstr != NULL) { + const char *def = scanned_member->field->default_value; + if (*pstr != NULL && *pstr != def) + do_free(allocator, *pstr); + } + *pstr = do_alloc(allocator, len - pref_len + 1); + if (*pstr == NULL) + return FALSE; + memcpy(*pstr, data + pref_len, len - pref_len); + (*pstr)[len - pref_len] = 0; + return TRUE; + } + case PROTOBUF_C_TYPE_BYTES: { + ProtobufCBinaryData *bd = member; + const ProtobufCBinaryData *def_bd; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + def_bd = scanned_member->field->default_value; + if (maybe_clear && + bd->data != NULL && + (def_bd == NULL || bd->data != def_bd->data)) + { + do_free(allocator, bd->data); + } + if (len > pref_len) { + bd->data = do_alloc(allocator, len - pref_len); + if (bd->data == NULL) + return FALSE; + memcpy(bd->data, data + pref_len, len - pref_len); + } else { + bd->data = NULL; + } + bd->len = len - pref_len; + return TRUE; + } + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage **pmessage = member; + ProtobufCMessage *subm; + const ProtobufCMessage *def_mess; + protobuf_c_boolean merge_successful = TRUE; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + def_mess = scanned_member->field->default_value; + subm = protobuf_c_message_unpack(scanned_member->field->descriptor, + allocator, + len - pref_len, + data + pref_len); + + if (maybe_clear && + *pmessage != NULL && + *pmessage != def_mess) + { + if (subm != NULL) + merge_successful = merge_messages(*pmessage, subm, allocator); + /* Delete the previous message */ + protobuf_c_message_free_unpacked(*pmessage, allocator); + } + *pmessage = subm; + if (subm == NULL || !merge_successful) + return FALSE; + return TRUE; + } + } + return FALSE; +} + +static protobuf_c_boolean +parse_oneof_member (ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message, + scanned_member->field->quantifier_offset); + + /* If we have already parsed a member of this oneof, free it. */ + if (*oneof_case != 0) { + const ProtobufCFieldDescriptor *old_field; + size_t el_size; + /* lookup field */ + int field_index = + int_range_lookup(message->descriptor->n_field_ranges, + message->descriptor->field_ranges, + *oneof_case); + if (field_index < 0) + return FALSE; + old_field = message->descriptor->fields + field_index; + el_size = sizeof_elt_in_repeated_array(old_field->type); + + switch (old_field->type) { + case PROTOBUF_C_TYPE_STRING: { + char **pstr = member; + const char *def = old_field->default_value; + if (*pstr != NULL && *pstr != def) + do_free(allocator, *pstr); + break; + } + case PROTOBUF_C_TYPE_BYTES: { + ProtobufCBinaryData *bd = member; + const ProtobufCBinaryData *def_bd = old_field->default_value; + if (bd->data != NULL && + (def_bd == NULL || bd->data != def_bd->data)) + { + do_free(allocator, bd->data); + } + break; + } + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage **pmessage = member; + const ProtobufCMessage *def_mess = old_field->default_value; + if (*pmessage != NULL && *pmessage != def_mess) + protobuf_c_message_free_unpacked(*pmessage, allocator); + break; + } + default: + break; + } + + memset (member, 0, el_size); + } + if (!parse_required_member (scanned_member, member, allocator, TRUE)) + return FALSE; + + *oneof_case = scanned_member->tag; + return TRUE; +} + + +static protobuf_c_boolean +parse_optional_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + if (!parse_required_member(scanned_member, member, allocator, TRUE)) + return FALSE; + if (scanned_member->field->quantifier_offset != 0) + STRUCT_MEMBER(protobuf_c_boolean, + message, + scanned_member->field->quantifier_offset) = TRUE; + return TRUE; +} + +static protobuf_c_boolean +parse_repeated_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); + size_t siz = sizeof_elt_in_repeated_array(field->type); + char *array = *(char **) member; + + if (!parse_required_member(scanned_member, array + siz * (*p_n), + allocator, FALSE)) + { + return FALSE; + } + *p_n += 1; + return TRUE; +} + +static unsigned +scan_varint(unsigned len, const uint8_t *data) +{ + unsigned i; + if (len > 10) + len = 10; + for (i = 0; i < len; i++) + if ((data[i] & 0x80) == 0) + break; + if (i == len) + return 0; + return i + 1; +} + +static protobuf_c_boolean +parse_packed_repeated_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); + size_t siz = sizeof_elt_in_repeated_array(field->type); + void *array = *(char **) member + siz * (*p_n); + const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len; + size_t rem = scanned_member->len - scanned_member->length_prefix_len; + size_t count = 0; +#if defined(WORDS_BIGENDIAN) + unsigned i; +#endif + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + count = (scanned_member->len - scanned_member->length_prefix_len) / 4; +#if !defined(WORDS_BIGENDIAN) + goto no_unpacking_needed; +#else + for (i = 0; i < count; i++) { + ((uint32_t *) array)[i] = parse_fixed_uint32(at); + at += 4; + } + break; +#endif + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + count = (scanned_member->len - scanned_member->length_prefix_len) / 8; +#if !defined(WORDS_BIGENDIAN) + goto no_unpacking_needed; +#else + for (i = 0; i < count; i++) { + ((uint64_t *) array)[i] = parse_fixed_uint64(at); + at += 8; + } + break; +#endif + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value"); + return FALSE; + } + ((int32_t *) array)[count++] = parse_int32(s, at); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_SINT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value"); + return FALSE; + } + ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at)); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_UINT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value"); + return FALSE; + } + ((uint32_t *) array)[count++] = parse_uint32(s, at); + at += s; + rem -= s; + } + break; + + case PROTOBUF_C_TYPE_SINT64: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value"); + return FALSE; + } + ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at)); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value"); + return FALSE; + } + ((int64_t *) array)[count++] = parse_uint64(s, at); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_BOOL: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value"); + return FALSE; + } + ((protobuf_c_boolean *) array)[count++] = parse_boolean(s, at); + at += s; + rem -= s; + } + break; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + *p_n += count; + return TRUE; + +#if !defined(WORDS_BIGENDIAN) +no_unpacking_needed: + memcpy(array, at, count * siz); + *p_n += count; + return TRUE; +#endif +} + +static protobuf_c_boolean +is_packable_type(ProtobufCType type) +{ + return + type != PROTOBUF_C_TYPE_STRING && + type != PROTOBUF_C_TYPE_BYTES && + type != PROTOBUF_C_TYPE_MESSAGE; +} + +static protobuf_c_boolean +parse_member(ScannedMember *scanned_member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + void *member; + + if (field == NULL) { + ProtobufCMessageUnknownField *ufield = + message->unknown_fields + + (message->n_unknown_fields++); + ufield->tag = scanned_member->tag; + ufield->wire_type = scanned_member->wire_type; + ufield->len = scanned_member->len; + ufield->data = do_alloc(allocator, scanned_member->len); + if (ufield->data == NULL) + return FALSE; + memcpy(ufield->data, scanned_member->data, ufield->len); + return TRUE; + } + member = (char *) message + field->offset; + switch (field->label) { + case PROTOBUF_C_LABEL_REQUIRED: + return parse_required_member(scanned_member, member, + allocator, TRUE); + case PROTOBUF_C_LABEL_OPTIONAL: + case PROTOBUF_C_LABEL_NONE: + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) { + return parse_oneof_member(scanned_member, member, + message, allocator); + } else { + return parse_optional_member(scanned_member, member, + message, allocator); + } + case PROTOBUF_C_LABEL_REPEATED: + if (scanned_member->wire_type == + PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || + is_packable_type(field->type))) + { + return parse_packed_repeated_member(scanned_member, + member, message); + } else { + return parse_repeated_member(scanned_member, + member, message, + allocator); + } + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Initialise messages generated by old code. + * + * This function is used if desc->message_init == NULL (which occurs + * for old code, and which would be useful to support allocating + * descriptors dynamically). + */ +static void +message_init_generic(const ProtobufCMessageDescriptor *desc, + ProtobufCMessage *message) +{ + unsigned i; + + memset(message, 0, desc->sizeof_message); + message->descriptor = desc; + for (i = 0; i < desc->n_fields; i++) { + if (desc->fields[i].default_value != NULL && + desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED) + { + void *field = + STRUCT_MEMBER_P(message, desc->fields[i].offset); + const void *dv = desc->fields[i].default_value; + + switch (desc->fields[i].type) { + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + case PROTOBUF_C_TYPE_ENUM: + memcpy(field, dv, 4); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + memcpy(field, dv, 8); + break; + case PROTOBUF_C_TYPE_BOOL: + memcpy(field, dv, sizeof(protobuf_c_boolean)); + break; + case PROTOBUF_C_TYPE_BYTES: + memcpy(field, dv, sizeof(ProtobufCBinaryData)); + break; + + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_MESSAGE: + /* + * The next line essentially implements a cast + * from const, which is totally unavoidable. + */ + *(const void **) field = dv; + break; + } + } + } +} + +/**@}*/ + +/* + * ScannedMember slabs (an unpacking implementation detail). Before doing real + * unpacking, we first scan through the elements to see how many there are (for + * repeated fields), and which field to use (for non-repeated fields given + * twice). + * + * In order to avoid allocations for small messages, we keep a stack-allocated + * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we + * fill that up, we allocate each slab twice as large as the previous one. + */ +#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4 + +/* + * The number of slabs, including the stack-allocated ones; choose the number so + * that we would overflow if we needed a slab larger than provided. + */ +#define MAX_SCANNED_MEMBER_SLAB \ + (sizeof(unsigned int)*8 - 1 \ + - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \ + - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2) + +#define REQUIRED_FIELD_BITMAP_SET(index) \ + (required_fields_bitmap[(index)/8] |= (1UL<<((index)%8))) + +#define REQUIRED_FIELD_BITMAP_IS_SET(index) \ + (required_fields_bitmap[(index)/8] & (1UL<<((index)%8))) + +ProtobufCMessage * +protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc, + ProtobufCAllocator *allocator, + size_t len, const uint8_t *data) +{ + ProtobufCMessage *rv; + size_t rem = len; + const uint8_t *at = data; + const ProtobufCFieldDescriptor *last_field = desc->fields + 0; + ScannedMember first_member_slab[1UL << + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2]; + + /* + * scanned_member_slabs[i] is an array of arrays of ScannedMember. + * The first slab (scanned_member_slabs[0] is just a pointer to + * first_member_slab), above. All subsequent slabs will be allocated + * using the allocator. + */ + ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1]; + unsigned which_slab = 0; /* the slab we are currently populating */ + unsigned in_slab_index = 0; /* number of members in the slab */ + size_t n_unknown = 0; + unsigned f; + unsigned j; + unsigned i_slab; + unsigned last_field_index = 0; + unsigned required_fields_bitmap_len; + unsigned char required_fields_bitmap_stack[16]; + unsigned char *required_fields_bitmap = required_fields_bitmap_stack; + protobuf_c_boolean required_fields_bitmap_alloced = FALSE; + + ASSERT_IS_MESSAGE_DESCRIPTOR(desc); + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + + rv = do_alloc(allocator, desc->sizeof_message); + if (!rv) + return (NULL); + scanned_member_slabs[0] = first_member_slab; + + required_fields_bitmap_len = (desc->n_fields + 7) / 8; + if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) { + required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len); + if (!required_fields_bitmap) { + do_free(allocator, rv); + return (NULL); + } + required_fields_bitmap_alloced = TRUE; + } + memset(required_fields_bitmap, 0, required_fields_bitmap_len); + + /* + * Generated code always defines "message_init". However, we provide a + * fallback for (1) users of old protobuf-c generated-code that do not + * provide the function, and (2) descriptors constructed from some other + * source (most likely, direct construction from the .proto file). + */ + if (desc->message_init != NULL) + protobuf_c_message_init(desc, rv); + else + message_init_generic(desc, rv); + + while (rem > 0) { + uint32_t tag; + uint8_t wire_type; + size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type); + const ProtobufCFieldDescriptor *field; + ScannedMember tmp; + + if (used == 0) { + PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + /* + * \todo Consider optimizing for field[1].id == tag, if field[1] + * exists! + */ + if (last_field == NULL || last_field->id != tag) { + /* lookup field */ + int field_index = + int_range_lookup(desc->n_field_ranges, + desc->field_ranges, + tag); + if (field_index < 0) { + field = NULL; + n_unknown++; + } else { + field = desc->fields + field_index; + last_field = field; + last_field_index = field_index; + } + } else { + field = last_field; + } + + if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED) + REQUIRED_FIELD_BITMAP_SET(last_field_index); + + at += used; + rem -= used; + tmp.tag = tag; + tmp.wire_type = wire_type; + tmp.field = field; + tmp.data = at; + tmp.length_prefix_len = 0; + + switch (wire_type) { + case PROTOBUF_C_WIRE_TYPE_VARINT: { + unsigned max_len = rem < 10 ? rem : 10; + unsigned i; + + for (i = 0; i < max_len; i++) + if ((at[i] & 0x80) == 0) + break; + if (i == max_len) { + PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = i + 1; + break; + } + case PROTOBUF_C_WIRE_TYPE_64BIT: + if (rem < 8) { + PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = 8; + break; + case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: { + size_t pref_len; + + tmp.len = scan_length_prefixed_data(rem, at, &pref_len); + if (tmp.len == 0) { + /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */ + goto error_cleanup_during_scan; + } + tmp.length_prefix_len = pref_len; + break; + } + case PROTOBUF_C_WIRE_TYPE_32BIT: + if (rem < 4) { + PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = 4; + break; + default: + PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u", + wire_type, (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + + if (in_slab_index == (1UL << + (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2))) + { + size_t size; + + in_slab_index = 0; + if (which_slab == MAX_SCANNED_MEMBER_SLAB) { + PROTOBUF_C_UNPACK_ERROR("too many fields"); + goto error_cleanup_during_scan; + } + which_slab++; + size = sizeof(ScannedMember) + << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2); + scanned_member_slabs[which_slab] = do_alloc(allocator, size); + if (scanned_member_slabs[which_slab] == NULL) + goto error_cleanup_during_scan; + } + scanned_member_slabs[which_slab][in_slab_index++] = tmp; + + if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) { + size_t *n = STRUCT_MEMBER_PTR(size_t, rv, + field->quantifier_offset); + if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || + is_packable_type(field->type))) + { + size_t count; + if (!count_packed_elements(field->type, + tmp.len - + tmp.length_prefix_len, + tmp.data + + tmp.length_prefix_len, + &count)) + { + PROTOBUF_C_UNPACK_ERROR("counting packed elements"); + goto error_cleanup_during_scan; + } + *n += count; + } else { + *n += 1; + } + } + + at += tmp.len; + rem -= tmp.len; + } + + /* allocate space for repeated fields, also check that all required fields have been set */ + for (f = 0; f < desc->n_fields; f++) { + const ProtobufCFieldDescriptor *field = desc->fields + f; + if (field->label == PROTOBUF_C_LABEL_REPEATED) { + size_t siz = + sizeof_elt_in_repeated_array(field->type); + size_t *n_ptr = + STRUCT_MEMBER_PTR(size_t, rv, + field->quantifier_offset); + if (*n_ptr != 0) { + unsigned n = *n_ptr; + void *a; + *n_ptr = 0; + assert(rv->descriptor != NULL); +#define CLEAR_REMAINING_N_PTRS() \ + for(f++;f < desc->n_fields; f++) \ + { \ + field = desc->fields + f; \ + if (field->label == PROTOBUF_C_LABEL_REPEATED) \ + STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \ + } + a = do_alloc(allocator, siz * n); + if (!a) { + CLEAR_REMAINING_N_PTRS(); + goto error_cleanup; + } + STRUCT_MEMBER(void *, rv, field->offset) = a; + } + } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + if (field->default_value == NULL && + !REQUIRED_FIELD_BITMAP_IS_SET(f)) + { + CLEAR_REMAINING_N_PTRS(); + PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'", + desc->name, field->name); + goto error_cleanup; + } + } + } +#undef CLEAR_REMAINING_N_PTRS + + /* allocate space for unknown fields */ + if (n_unknown) { + rv->unknown_fields = do_alloc(allocator, + n_unknown * sizeof(ProtobufCMessageUnknownField)); + if (rv->unknown_fields == NULL) + goto error_cleanup; + } + + /* do real parsing */ + for (i_slab = 0; i_slab <= which_slab; i_slab++) { + unsigned max = (i_slab == which_slab) ? + in_slab_index : (1UL << (i_slab + 4)); + ScannedMember *slab = scanned_member_slabs[i_slab]; + + for (j = 0; j < max; j++) { + if (!parse_member(slab + j, rv, allocator)) { + PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s", + slab->field ? slab->field->name : "*unknown-field*", + desc->name); + goto error_cleanup; + } + } + } + + /* cleanup */ + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return rv; + +error_cleanup: + protobuf_c_message_free_unpacked(rv, allocator); + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return NULL; + +error_cleanup_during_scan: + do_free(allocator, rv); + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return NULL; +} + +void +protobuf_c_message_free_unpacked(ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCMessageDescriptor *desc; + unsigned f; + + if (message == NULL) + return; + + desc = message->descriptor; + + ASSERT_IS_MESSAGE(message); + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + message->descriptor = NULL; + for (f = 0; f < desc->n_fields; f++) { + if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) && + desc->fields[f].id != + STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset)) + { + /* This is not the selected oneof, skip it */ + continue; + } + + if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) { + size_t n = STRUCT_MEMBER(size_t, + message, + desc->fields[f].quantifier_offset); + void *arr = STRUCT_MEMBER(void *, + message, + desc->fields[f].offset); + + if (arr != NULL) { + if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { + unsigned i; + for (i = 0; i < n; i++) + do_free(allocator, ((char **) arr)[i]); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { + unsigned i; + for (i = 0; i < n; i++) + do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { + unsigned i; + for (i = 0; i < n; i++) + protobuf_c_message_free_unpacked( + ((ProtobufCMessage **) arr)[i], + allocator + ); + } + do_free(allocator, arr); + } + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { + char *str = STRUCT_MEMBER(char *, message, + desc->fields[f].offset); + + if (str && str != desc->fields[f].default_value) + do_free(allocator, str); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { + void *data = STRUCT_MEMBER(ProtobufCBinaryData, message, + desc->fields[f].offset).data; + const ProtobufCBinaryData *default_bd; + + default_bd = desc->fields[f].default_value; + if (data != NULL && + (default_bd == NULL || + default_bd->data != data)) + { + do_free(allocator, data); + } + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage *sm; + + sm = STRUCT_MEMBER(ProtobufCMessage *, message, + desc->fields[f].offset); + if (sm && sm != desc->fields[f].default_value) + protobuf_c_message_free_unpacked(sm, allocator); + } + } + + for (f = 0; f < message->n_unknown_fields; f++) + do_free(allocator, message->unknown_fields[f].data); + if (message->unknown_fields != NULL) + do_free(allocator, message->unknown_fields); + + do_free(allocator, message); +} + +void +protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor, + void *message) +{ + descriptor->message_init((ProtobufCMessage *) (message)); +} + +protobuf_c_boolean +protobuf_c_message_check(const ProtobufCMessage *message) +{ + unsigned i; + + if (!message || + !message->descriptor || + message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) + { + return FALSE; + } + + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *f = message->descriptor->fields + i; + ProtobufCType type = f->type; + ProtobufCLabel label = f->label; + void *field = STRUCT_MEMBER_P (message, f->offset); + + if (f->flags & PROTOBUF_C_FIELD_FLAG_ONEOF) { + const uint32_t *oneof_case = STRUCT_MEMBER_P (message, f->quantifier_offset); + if (f->id != *oneof_case) { + continue; //Do not check if it is an unpopulated oneof member. + } + } + + if (label == PROTOBUF_C_LABEL_REPEATED) { + size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset); + + if (*quantity > 0 && *(void **) field == NULL) { + return FALSE; + } + + if (type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage **submessage = *(ProtobufCMessage ***) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (!protobuf_c_message_check(submessage[j])) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_STRING) { + char **string = *(char ***) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (!string[j]) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_BYTES) { + ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (bd[j].len > 0 && bd[j].data == NULL) + return FALSE; + } + } + + } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */ + + if (type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage *submessage = *(ProtobufCMessage **) field; + if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) { + if (!protobuf_c_message_check(submessage)) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_STRING) { + char *string = *(char **) field; + if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL) + return FALSE; + } else if (type == PROTOBUF_C_TYPE_BYTES) { + protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset); + ProtobufCBinaryData *bd = field; + if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) { + if (bd->len > 0 && bd->data == NULL) + return FALSE; + } + } + } + } + + return TRUE; +} + +/* === services === */ + +typedef void (*GenericHandler) (void *service, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data); +void +protobuf_c_service_invoke_internal(ProtobufCService *service, + unsigned method_index, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data) +{ + GenericHandler *handlers; + GenericHandler handler; + + /* + * Verify that method_index is within range. If this fails, you are + * likely invoking a newly added method on an old service. (Although + * other memory corruption bugs can cause this assertion too.) + */ + assert(method_index < service->descriptor->n_methods); + + /* + * Get the array of virtual methods (which are enumerated by the + * generated code). + */ + handlers = (GenericHandler *) (service + 1); + + /* + * Get our method and invoke it. + * \todo Seems like handler == NULL is a situation that needs handling. + */ + handler = handlers[method_index]; + (*handler)(service, input, closure, closure_data); +} + +void +protobuf_c_service_generated_init(ProtobufCService *service, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCServiceDestroy destroy) +{ + ASSERT_IS_SERVICE_DESCRIPTOR(descriptor); + service->descriptor = descriptor; + service->destroy = destroy; + service->invoke = protobuf_c_service_invoke_internal; + memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler)); +} + +void protobuf_c_service_destroy(ProtobufCService *service) +{ + service->destroy(service); +} + +/* --- querying the descriptors --- */ + +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + + if (desc == NULL || desc->values_by_name == NULL) + return NULL; + + count = desc->n_value_names; + + while (count > 1) { + unsigned mid = start + count / 2; + int rv = strcmp(desc->values_by_name[mid].name, name); + if (rv == 0) + return desc->values + desc->values_by_name[mid].index; + else if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else + count = mid - start; + } + if (count == 0) + return NULL; + if (strcmp(desc->values_by_name[start].name, name) == 0) + return desc->values + desc->values_by_name[start].index; + return NULL; +} + +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc, + int value) +{ + int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value); + if (rv < 0) + return NULL; + return desc->values + rv; +} + +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + const ProtobufCFieldDescriptor *field; + + if (desc == NULL || desc->fields_sorted_by_name == NULL) + return NULL; + + count = desc->n_fields; + + while (count > 1) { + unsigned mid = start + count / 2; + int rv; + field = desc->fields + desc->fields_sorted_by_name[mid]; + rv = strcmp(field->name, name); + if (rv == 0) + return field; + else if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else + count = mid - start; + } + if (count == 0) + return NULL; + field = desc->fields + desc->fields_sorted_by_name[start]; + if (strcmp(field->name, name) == 0) + return field; + return NULL; +} + +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc, + unsigned value) +{ + int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value); + if (rv < 0) + return NULL; + return desc->fields + rv; +} + +const ProtobufCMethodDescriptor * +protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + + if (desc == NULL || desc->method_indices_by_name == NULL) + return NULL; + + count = desc->n_methods; + + while (count > 1) { + unsigned mid = start + count / 2; + unsigned mid_index = desc->method_indices_by_name[mid]; + const char *mid_name = desc->methods[mid_index].name; + int rv = strcmp(mid_name, name); + + if (rv == 0) + return desc->methods + desc->method_indices_by_name[mid]; + if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else { + count = mid - start; + } + } + if (count == 0) + return NULL; + if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0) + return desc->methods + desc->method_indices_by_name[start]; + return NULL; +} diff --git a/fluent-bit/lib/cmetrics/src/external/remote.pb-c.c b/fluent-bit/lib/cmetrics/src/external/remote.pb-c.c new file mode 100644 index 00000000..c26695eb --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/remote.pb-c.c @@ -0,0 +1,615 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: remote.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include <prometheus_remote_write/remote.pb-c.h> + +void prometheus__write_request__init + (Prometheus__WriteRequest *message) +{ + static const Prometheus__WriteRequest init_value = PROMETHEUS__WRITE_REQUEST__INIT; + *message = init_value; +} +size_t prometheus__write_request__get_packed_size + (const Prometheus__WriteRequest *message) +{ + assert(message->base.descriptor == &prometheus__write_request__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__write_request__pack + (const Prometheus__WriteRequest *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__write_request__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__write_request__pack_to_buffer + (const Prometheus__WriteRequest *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__write_request__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__WriteRequest * + prometheus__write_request__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__WriteRequest *) + protobuf_c_message_unpack (&prometheus__write_request__descriptor, + allocator, len, data); +} +void prometheus__write_request__free_unpacked + (Prometheus__WriteRequest *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__write_request__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__read_request__init + (Prometheus__ReadRequest *message) +{ + static const Prometheus__ReadRequest init_value = PROMETHEUS__READ_REQUEST__INIT; + *message = init_value; +} +size_t prometheus__read_request__get_packed_size + (const Prometheus__ReadRequest *message) +{ + assert(message->base.descriptor == &prometheus__read_request__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__read_request__pack + (const Prometheus__ReadRequest *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__read_request__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__read_request__pack_to_buffer + (const Prometheus__ReadRequest *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__read_request__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__ReadRequest * + prometheus__read_request__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__ReadRequest *) + protobuf_c_message_unpack (&prometheus__read_request__descriptor, + allocator, len, data); +} +void prometheus__read_request__free_unpacked + (Prometheus__ReadRequest *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__read_request__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__read_response__init + (Prometheus__ReadResponse *message) +{ + static const Prometheus__ReadResponse init_value = PROMETHEUS__READ_RESPONSE__INIT; + *message = init_value; +} +size_t prometheus__read_response__get_packed_size + (const Prometheus__ReadResponse *message) +{ + assert(message->base.descriptor == &prometheus__read_response__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__read_response__pack + (const Prometheus__ReadResponse *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__read_response__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__read_response__pack_to_buffer + (const Prometheus__ReadResponse *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__read_response__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__ReadResponse * + prometheus__read_response__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__ReadResponse *) + protobuf_c_message_unpack (&prometheus__read_response__descriptor, + allocator, len, data); +} +void prometheus__read_response__free_unpacked + (Prometheus__ReadResponse *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__read_response__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__query__init + (Prometheus__Query *message) +{ + static const Prometheus__Query init_value = PROMETHEUS__QUERY__INIT; + *message = init_value; +} +size_t prometheus__query__get_packed_size + (const Prometheus__Query *message) +{ + assert(message->base.descriptor == &prometheus__query__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__query__pack + (const Prometheus__Query *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__query__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__query__pack_to_buffer + (const Prometheus__Query *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__query__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__Query * + prometheus__query__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__Query *) + protobuf_c_message_unpack (&prometheus__query__descriptor, + allocator, len, data); +} +void prometheus__query__free_unpacked + (Prometheus__Query *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__query__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__query_result__init + (Prometheus__QueryResult *message) +{ + static const Prometheus__QueryResult init_value = PROMETHEUS__QUERY_RESULT__INIT; + *message = init_value; +} +size_t prometheus__query_result__get_packed_size + (const Prometheus__QueryResult *message) +{ + assert(message->base.descriptor == &prometheus__query_result__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__query_result__pack + (const Prometheus__QueryResult *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__query_result__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__query_result__pack_to_buffer + (const Prometheus__QueryResult *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__query_result__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__QueryResult * + prometheus__query_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__QueryResult *) + protobuf_c_message_unpack (&prometheus__query_result__descriptor, + allocator, len, data); +} +void prometheus__query_result__free_unpacked + (Prometheus__QueryResult *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__query_result__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__chunked_read_response__init + (Prometheus__ChunkedReadResponse *message) +{ + static const Prometheus__ChunkedReadResponse init_value = PROMETHEUS__CHUNKED_READ_RESPONSE__INIT; + *message = init_value; +} +size_t prometheus__chunked_read_response__get_packed_size + (const Prometheus__ChunkedReadResponse *message) +{ + assert(message->base.descriptor == &prometheus__chunked_read_response__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__chunked_read_response__pack + (const Prometheus__ChunkedReadResponse *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__chunked_read_response__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__chunked_read_response__pack_to_buffer + (const Prometheus__ChunkedReadResponse *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__chunked_read_response__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__ChunkedReadResponse * + prometheus__chunked_read_response__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__ChunkedReadResponse *) + protobuf_c_message_unpack (&prometheus__chunked_read_response__descriptor, + allocator, len, data); +} +void prometheus__chunked_read_response__free_unpacked + (Prometheus__ChunkedReadResponse *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__chunked_read_response__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor prometheus__write_request__field_descriptors[2] = +{ + { + "timeseries", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__WriteRequest, n_timeseries), + offsetof(Prometheus__WriteRequest, timeseries), + &prometheus__time_series__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "metadata", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__WriteRequest, n_metadata), + offsetof(Prometheus__WriteRequest, metadata), + &prometheus__metric_metadata__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__write_request__field_indices_by_name[] = { + 1, /* field[1] = metadata */ + 0, /* field[0] = timeseries */ +}; +static const ProtobufCIntRange prometheus__write_request__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 3, 1 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__write_request__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.WriteRequest", + "WriteRequest", + "Prometheus__WriteRequest", + "prometheus", + sizeof(Prometheus__WriteRequest), + 2, + prometheus__write_request__field_descriptors, + prometheus__write_request__field_indices_by_name, + 2, prometheus__write_request__number_ranges, + (ProtobufCMessageInit) prometheus__write_request__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue prometheus__read_request__response_type__enum_values_by_number[2] = +{ + { "SAMPLES", "PROMETHEUS__READ_REQUEST__RESPONSE_TYPE__SAMPLES", 0 }, + { "STREAMED_XOR_CHUNKS", "PROMETHEUS__READ_REQUEST__RESPONSE_TYPE__STREAMED_XOR_CHUNKS", 1 }, +}; +static const ProtobufCIntRange prometheus__read_request__response_type__value_ranges[] = { +{0, 0},{0, 2} +}; +static const ProtobufCEnumValueIndex prometheus__read_request__response_type__enum_values_by_name[2] = +{ + { "SAMPLES", 0 }, + { "STREAMED_XOR_CHUNKS", 1 }, +}; +const ProtobufCEnumDescriptor prometheus__read_request__response_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "prometheus.ReadRequest.ResponseType", + "ResponseType", + "Prometheus__ReadRequest__ResponseType", + "prometheus", + 2, + prometheus__read_request__response_type__enum_values_by_number, + 2, + prometheus__read_request__response_type__enum_values_by_name, + 1, + prometheus__read_request__response_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor prometheus__read_request__field_descriptors[2] = +{ + { + "queries", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__ReadRequest, n_queries), + offsetof(Prometheus__ReadRequest, queries), + &prometheus__query__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "accepted_response_types", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_ENUM, + offsetof(Prometheus__ReadRequest, n_accepted_response_types), + offsetof(Prometheus__ReadRequest, accepted_response_types), + &prometheus__read_request__response_type__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__read_request__field_indices_by_name[] = { + 1, /* field[1] = accepted_response_types */ + 0, /* field[0] = queries */ +}; +static const ProtobufCIntRange prometheus__read_request__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__read_request__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.ReadRequest", + "ReadRequest", + "Prometheus__ReadRequest", + "prometheus", + sizeof(Prometheus__ReadRequest), + 2, + prometheus__read_request__field_descriptors, + prometheus__read_request__field_indices_by_name, + 1, prometheus__read_request__number_ranges, + (ProtobufCMessageInit) prometheus__read_request__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__read_response__field_descriptors[1] = +{ + { + "results", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__ReadResponse, n_results), + offsetof(Prometheus__ReadResponse, results), + &prometheus__query_result__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__read_response__field_indices_by_name[] = { + 0, /* field[0] = results */ +}; +static const ProtobufCIntRange prometheus__read_response__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor prometheus__read_response__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.ReadResponse", + "ReadResponse", + "Prometheus__ReadResponse", + "prometheus", + sizeof(Prometheus__ReadResponse), + 1, + prometheus__read_response__field_descriptors, + prometheus__read_response__field_indices_by_name, + 1, prometheus__read_response__number_ranges, + (ProtobufCMessageInit) prometheus__read_response__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__query__field_descriptors[4] = +{ + { + "start_timestamp_ms", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__Query, start_timestamp_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "end_timestamp_ms", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__Query, end_timestamp_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "matchers", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__Query, n_matchers), + offsetof(Prometheus__Query, matchers), + &prometheus__label_matcher__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "hints", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Prometheus__Query, hints), + &prometheus__read_hints__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__query__field_indices_by_name[] = { + 1, /* field[1] = end_timestamp_ms */ + 3, /* field[3] = hints */ + 2, /* field[2] = matchers */ + 0, /* field[0] = start_timestamp_ms */ +}; +static const ProtobufCIntRange prometheus__query__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor prometheus__query__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.Query", + "Query", + "Prometheus__Query", + "prometheus", + sizeof(Prometheus__Query), + 4, + prometheus__query__field_descriptors, + prometheus__query__field_indices_by_name, + 1, prometheus__query__number_ranges, + (ProtobufCMessageInit) prometheus__query__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__query_result__field_descriptors[1] = +{ + { + "timeseries", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__QueryResult, n_timeseries), + offsetof(Prometheus__QueryResult, timeseries), + &prometheus__time_series__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__query_result__field_indices_by_name[] = { + 0, /* field[0] = timeseries */ +}; +static const ProtobufCIntRange prometheus__query_result__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor prometheus__query_result__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.QueryResult", + "QueryResult", + "Prometheus__QueryResult", + "prometheus", + sizeof(Prometheus__QueryResult), + 1, + prometheus__query_result__field_descriptors, + prometheus__query_result__field_indices_by_name, + 1, prometheus__query_result__number_ranges, + (ProtobufCMessageInit) prometheus__query_result__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__chunked_read_response__field_descriptors[2] = +{ + { + "chunked_series", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__ChunkedReadResponse, n_chunked_series), + offsetof(Prometheus__ChunkedReadResponse, chunked_series), + &prometheus__chunked_series__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "query_index", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__ChunkedReadResponse, query_index), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__chunked_read_response__field_indices_by_name[] = { + 0, /* field[0] = chunked_series */ + 1, /* field[1] = query_index */ +}; +static const ProtobufCIntRange prometheus__chunked_read_response__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__chunked_read_response__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.ChunkedReadResponse", + "ChunkedReadResponse", + "Prometheus__ChunkedReadResponse", + "prometheus", + sizeof(Prometheus__ChunkedReadResponse), + 2, + prometheus__chunked_read_response__field_descriptors, + prometheus__chunked_read_response__field_indices_by_name, + 1, prometheus__chunked_read_response__number_ranges, + (ProtobufCMessageInit) prometheus__chunked_read_response__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/fluent-bit/lib/cmetrics/src/external/types.pb-c.c b/fluent-bit/lib/cmetrics/src/external/types.pb-c.c new file mode 100644 index 00000000..78281593 --- /dev/null +++ b/fluent-bit/lib/cmetrics/src/external/types.pb-c.c @@ -0,0 +1,1092 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: types.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include <prometheus_remote_write/types.pb-c.h> + +void prometheus__metric_metadata__init + (Prometheus__MetricMetadata *message) +{ + static const Prometheus__MetricMetadata init_value = PROMETHEUS__METRIC_METADATA__INIT; + *message = init_value; +} +size_t prometheus__metric_metadata__get_packed_size + (const Prometheus__MetricMetadata *message) +{ + assert(message->base.descriptor == &prometheus__metric_metadata__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__metric_metadata__pack + (const Prometheus__MetricMetadata *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__metric_metadata__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__metric_metadata__pack_to_buffer + (const Prometheus__MetricMetadata *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__metric_metadata__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__MetricMetadata * + prometheus__metric_metadata__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__MetricMetadata *) + protobuf_c_message_unpack (&prometheus__metric_metadata__descriptor, + allocator, len, data); +} +void prometheus__metric_metadata__free_unpacked + (Prometheus__MetricMetadata *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__metric_metadata__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__sample__init + (Prometheus__Sample *message) +{ + static const Prometheus__Sample init_value = PROMETHEUS__SAMPLE__INIT; + *message = init_value; +} +size_t prometheus__sample__get_packed_size + (const Prometheus__Sample *message) +{ + assert(message->base.descriptor == &prometheus__sample__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__sample__pack + (const Prometheus__Sample *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__sample__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__sample__pack_to_buffer + (const Prometheus__Sample *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__sample__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__Sample * + prometheus__sample__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__Sample *) + protobuf_c_message_unpack (&prometheus__sample__descriptor, + allocator, len, data); +} +void prometheus__sample__free_unpacked + (Prometheus__Sample *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__sample__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__time_series__init + (Prometheus__TimeSeries *message) +{ + static const Prometheus__TimeSeries init_value = PROMETHEUS__TIME_SERIES__INIT; + *message = init_value; +} +size_t prometheus__time_series__get_packed_size + (const Prometheus__TimeSeries *message) +{ + assert(message->base.descriptor == &prometheus__time_series__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__time_series__pack + (const Prometheus__TimeSeries *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__time_series__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__time_series__pack_to_buffer + (const Prometheus__TimeSeries *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__time_series__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__TimeSeries * + prometheus__time_series__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__TimeSeries *) + protobuf_c_message_unpack (&prometheus__time_series__descriptor, + allocator, len, data); +} +void prometheus__time_series__free_unpacked + (Prometheus__TimeSeries *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__time_series__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__label__init + (Prometheus__Label *message) +{ + static const Prometheus__Label init_value = PROMETHEUS__LABEL__INIT; + *message = init_value; +} +size_t prometheus__label__get_packed_size + (const Prometheus__Label *message) +{ + assert(message->base.descriptor == &prometheus__label__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__label__pack + (const Prometheus__Label *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__label__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__label__pack_to_buffer + (const Prometheus__Label *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__label__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__Label * + prometheus__label__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__Label *) + protobuf_c_message_unpack (&prometheus__label__descriptor, + allocator, len, data); +} +void prometheus__label__free_unpacked + (Prometheus__Label *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__label__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__labels__init + (Prometheus__Labels *message) +{ + static const Prometheus__Labels init_value = PROMETHEUS__LABELS__INIT; + *message = init_value; +} +size_t prometheus__labels__get_packed_size + (const Prometheus__Labels *message) +{ + assert(message->base.descriptor == &prometheus__labels__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__labels__pack + (const Prometheus__Labels *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__labels__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__labels__pack_to_buffer + (const Prometheus__Labels *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__labels__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__Labels * + prometheus__labels__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__Labels *) + protobuf_c_message_unpack (&prometheus__labels__descriptor, + allocator, len, data); +} +void prometheus__labels__free_unpacked + (Prometheus__Labels *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__labels__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__label_matcher__init + (Prometheus__LabelMatcher *message) +{ + static const Prometheus__LabelMatcher init_value = PROMETHEUS__LABEL_MATCHER__INIT; + *message = init_value; +} +size_t prometheus__label_matcher__get_packed_size + (const Prometheus__LabelMatcher *message) +{ + assert(message->base.descriptor == &prometheus__label_matcher__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__label_matcher__pack + (const Prometheus__LabelMatcher *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__label_matcher__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__label_matcher__pack_to_buffer + (const Prometheus__LabelMatcher *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__label_matcher__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__LabelMatcher * + prometheus__label_matcher__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__LabelMatcher *) + protobuf_c_message_unpack (&prometheus__label_matcher__descriptor, + allocator, len, data); +} +void prometheus__label_matcher__free_unpacked + (Prometheus__LabelMatcher *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__label_matcher__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__read_hints__init + (Prometheus__ReadHints *message) +{ + static const Prometheus__ReadHints init_value = PROMETHEUS__READ_HINTS__INIT; + *message = init_value; +} +size_t prometheus__read_hints__get_packed_size + (const Prometheus__ReadHints *message) +{ + assert(message->base.descriptor == &prometheus__read_hints__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__read_hints__pack + (const Prometheus__ReadHints *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__read_hints__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__read_hints__pack_to_buffer + (const Prometheus__ReadHints *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__read_hints__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__ReadHints * + prometheus__read_hints__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__ReadHints *) + protobuf_c_message_unpack (&prometheus__read_hints__descriptor, + allocator, len, data); +} +void prometheus__read_hints__free_unpacked + (Prometheus__ReadHints *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__read_hints__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__chunk__init + (Prometheus__Chunk *message) +{ + static const Prometheus__Chunk init_value = PROMETHEUS__CHUNK__INIT; + *message = init_value; +} +size_t prometheus__chunk__get_packed_size + (const Prometheus__Chunk *message) +{ + assert(message->base.descriptor == &prometheus__chunk__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__chunk__pack + (const Prometheus__Chunk *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__chunk__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__chunk__pack_to_buffer + (const Prometheus__Chunk *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__chunk__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__Chunk * + prometheus__chunk__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__Chunk *) + protobuf_c_message_unpack (&prometheus__chunk__descriptor, + allocator, len, data); +} +void prometheus__chunk__free_unpacked + (Prometheus__Chunk *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__chunk__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__chunked_series__init + (Prometheus__ChunkedSeries *message) +{ + static const Prometheus__ChunkedSeries init_value = PROMETHEUS__CHUNKED_SERIES__INIT; + *message = init_value; +} +size_t prometheus__chunked_series__get_packed_size + (const Prometheus__ChunkedSeries *message) +{ + assert(message->base.descriptor == &prometheus__chunked_series__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__chunked_series__pack + (const Prometheus__ChunkedSeries *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__chunked_series__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__chunked_series__pack_to_buffer + (const Prometheus__ChunkedSeries *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__chunked_series__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__ChunkedSeries * + prometheus__chunked_series__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__ChunkedSeries *) + protobuf_c_message_unpack (&prometheus__chunked_series__descriptor, + allocator, len, data); +} +void prometheus__chunked_series__free_unpacked + (Prometheus__ChunkedSeries *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__chunked_series__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCEnumValue prometheus__metric_metadata__metric_type__enum_values_by_number[8] = +{ + { "UNKNOWN", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__UNKNOWN", 0 }, + { "COUNTER", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__COUNTER", 1 }, + { "GAUGE", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__GAUGE", 2 }, + { "HISTOGRAM", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__HISTOGRAM", 3 }, + { "GAUGEHISTOGRAM", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__GAUGEHISTOGRAM", 4 }, + { "SUMMARY", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__SUMMARY", 5 }, + { "INFO", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__INFO", 6 }, + { "STATESET", "PROMETHEUS__METRIC_METADATA__METRIC_TYPE__STATESET", 7 }, +}; +static const ProtobufCIntRange prometheus__metric_metadata__metric_type__value_ranges[] = { +{0, 0},{0, 8} +}; +static const ProtobufCEnumValueIndex prometheus__metric_metadata__metric_type__enum_values_by_name[8] = +{ + { "COUNTER", 1 }, + { "GAUGE", 2 }, + { "GAUGEHISTOGRAM", 4 }, + { "HISTOGRAM", 3 }, + { "INFO", 6 }, + { "STATESET", 7 }, + { "SUMMARY", 5 }, + { "UNKNOWN", 0 }, +}; +const ProtobufCEnumDescriptor prometheus__metric_metadata__metric_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "prometheus.MetricMetadata.MetricType", + "MetricType", + "Prometheus__MetricMetadata__MetricType", + "prometheus", + 8, + prometheus__metric_metadata__metric_type__enum_values_by_number, + 8, + prometheus__metric_metadata__metric_type__enum_values_by_name, + 1, + prometheus__metric_metadata__metric_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor prometheus__metric_metadata__field_descriptors[4] = +{ + { + "type", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Prometheus__MetricMetadata, type), + &prometheus__metric_metadata__metric_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "metric_family_name", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__MetricMetadata, metric_family_name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "help", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__MetricMetadata, help), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "unit", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__MetricMetadata, unit), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__metric_metadata__field_indices_by_name[] = { + 2, /* field[2] = help */ + 1, /* field[1] = metric_family_name */ + 0, /* field[0] = type */ + 3, /* field[3] = unit */ +}; +static const ProtobufCIntRange prometheus__metric_metadata__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 4, 2 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor prometheus__metric_metadata__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.MetricMetadata", + "MetricMetadata", + "Prometheus__MetricMetadata", + "prometheus", + sizeof(Prometheus__MetricMetadata), + 4, + prometheus__metric_metadata__field_descriptors, + prometheus__metric_metadata__field_indices_by_name, + 2, prometheus__metric_metadata__number_ranges, + (ProtobufCMessageInit) prometheus__metric_metadata__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__sample__field_descriptors[2] = +{ + { + "value", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Prometheus__Sample, value), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "timestamp", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__Sample, timestamp), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__sample__field_indices_by_name[] = { + 1, /* field[1] = timestamp */ + 0, /* field[0] = value */ +}; +static const ProtobufCIntRange prometheus__sample__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__sample__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.Sample", + "Sample", + "Prometheus__Sample", + "prometheus", + sizeof(Prometheus__Sample), + 2, + prometheus__sample__field_descriptors, + prometheus__sample__field_indices_by_name, + 1, prometheus__sample__number_ranges, + (ProtobufCMessageInit) prometheus__sample__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__time_series__field_descriptors[2] = +{ + { + "labels", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__TimeSeries, n_labels), + offsetof(Prometheus__TimeSeries, labels), + &prometheus__label__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "samples", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__TimeSeries, n_samples), + offsetof(Prometheus__TimeSeries, samples), + &prometheus__sample__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__time_series__field_indices_by_name[] = { + 0, /* field[0] = labels */ + 1, /* field[1] = samples */ +}; +static const ProtobufCIntRange prometheus__time_series__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__time_series__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.TimeSeries", + "TimeSeries", + "Prometheus__TimeSeries", + "prometheus", + sizeof(Prometheus__TimeSeries), + 2, + prometheus__time_series__field_descriptors, + prometheus__time_series__field_indices_by_name, + 1, prometheus__time_series__number_ranges, + (ProtobufCMessageInit) prometheus__time_series__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__label__field_descriptors[2] = +{ + { + "name", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__Label, name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__Label, value), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__label__field_indices_by_name[] = { + 0, /* field[0] = name */ + 1, /* field[1] = value */ +}; +static const ProtobufCIntRange prometheus__label__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__label__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.Label", + "Label", + "Prometheus__Label", + "prometheus", + sizeof(Prometheus__Label), + 2, + prometheus__label__field_descriptors, + prometheus__label__field_indices_by_name, + 1, prometheus__label__number_ranges, + (ProtobufCMessageInit) prometheus__label__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__labels__field_descriptors[1] = +{ + { + "labels", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__Labels, n_labels), + offsetof(Prometheus__Labels, labels), + &prometheus__label__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__labels__field_indices_by_name[] = { + 0, /* field[0] = labels */ +}; +static const ProtobufCIntRange prometheus__labels__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor prometheus__labels__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.Labels", + "Labels", + "Prometheus__Labels", + "prometheus", + sizeof(Prometheus__Labels), + 1, + prometheus__labels__field_descriptors, + prometheus__labels__field_indices_by_name, + 1, prometheus__labels__number_ranges, + (ProtobufCMessageInit) prometheus__labels__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue prometheus__label_matcher__type__enum_values_by_number[4] = +{ + { "EQ", "PROMETHEUS__LABEL_MATCHER__TYPE__EQ", 0 }, + { "NEQ", "PROMETHEUS__LABEL_MATCHER__TYPE__NEQ", 1 }, + { "RE", "PROMETHEUS__LABEL_MATCHER__TYPE__RE", 2 }, + { "NRE", "PROMETHEUS__LABEL_MATCHER__TYPE__NRE", 3 }, +}; +static const ProtobufCIntRange prometheus__label_matcher__type__value_ranges[] = { +{0, 0},{0, 4} +}; +static const ProtobufCEnumValueIndex prometheus__label_matcher__type__enum_values_by_name[4] = +{ + { "EQ", 0 }, + { "NEQ", 1 }, + { "NRE", 3 }, + { "RE", 2 }, +}; +const ProtobufCEnumDescriptor prometheus__label_matcher__type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "prometheus.LabelMatcher.Type", + "Type", + "Prometheus__LabelMatcher__Type", + "prometheus", + 4, + prometheus__label_matcher__type__enum_values_by_number, + 4, + prometheus__label_matcher__type__enum_values_by_name, + 1, + prometheus__label_matcher__type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor prometheus__label_matcher__field_descriptors[3] = +{ + { + "type", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Prometheus__LabelMatcher, type), + &prometheus__label_matcher__type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "name", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__LabelMatcher, name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__LabelMatcher, value), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__label_matcher__field_indices_by_name[] = { + 1, /* field[1] = name */ + 0, /* field[0] = type */ + 2, /* field[2] = value */ +}; +static const ProtobufCIntRange prometheus__label_matcher__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor prometheus__label_matcher__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.LabelMatcher", + "LabelMatcher", + "Prometheus__LabelMatcher", + "prometheus", + sizeof(Prometheus__LabelMatcher), + 3, + prometheus__label_matcher__field_descriptors, + prometheus__label_matcher__field_indices_by_name, + 1, prometheus__label_matcher__number_ranges, + (ProtobufCMessageInit) prometheus__label_matcher__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__read_hints__field_descriptors[7] = +{ + { + "step_ms", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__ReadHints, step_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "func", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Prometheus__ReadHints, func), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "start_ms", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__ReadHints, start_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "end_ms", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__ReadHints, end_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "grouping", + 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_STRING, + offsetof(Prometheus__ReadHints, n_grouping), + offsetof(Prometheus__ReadHints, grouping), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "by", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Prometheus__ReadHints, by), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "range_ms", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__ReadHints, range_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__read_hints__field_indices_by_name[] = { + 5, /* field[5] = by */ + 3, /* field[3] = end_ms */ + 1, /* field[1] = func */ + 4, /* field[4] = grouping */ + 6, /* field[6] = range_ms */ + 2, /* field[2] = start_ms */ + 0, /* field[0] = step_ms */ +}; +static const ProtobufCIntRange prometheus__read_hints__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor prometheus__read_hints__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.ReadHints", + "ReadHints", + "Prometheus__ReadHints", + "prometheus", + sizeof(Prometheus__ReadHints), + 7, + prometheus__read_hints__field_descriptors, + prometheus__read_hints__field_indices_by_name, + 1, prometheus__read_hints__number_ranges, + (ProtobufCMessageInit) prometheus__read_hints__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue prometheus__chunk__encoding__enum_values_by_number[2] = +{ + { "UNKNOWN", "PROMETHEUS__CHUNK__ENCODING__UNKNOWN", 0 }, + { "XOR", "PROMETHEUS__CHUNK__ENCODING__XOR", 1 }, +}; +static const ProtobufCIntRange prometheus__chunk__encoding__value_ranges[] = { +{0, 0},{0, 2} +}; +static const ProtobufCEnumValueIndex prometheus__chunk__encoding__enum_values_by_name[2] = +{ + { "UNKNOWN", 0 }, + { "XOR", 1 }, +}; +const ProtobufCEnumDescriptor prometheus__chunk__encoding__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "prometheus.Chunk.Encoding", + "Encoding", + "Prometheus__Chunk__Encoding", + "prometheus", + 2, + prometheus__chunk__encoding__enum_values_by_number, + 2, + prometheus__chunk__encoding__enum_values_by_name, + 1, + prometheus__chunk__encoding__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor prometheus__chunk__field_descriptors[4] = +{ + { + "min_time_ms", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__Chunk, min_time_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "max_time_ms", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__Chunk, max_time_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "type", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Prometheus__Chunk, type), + &prometheus__chunk__encoding__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "data", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Prometheus__Chunk, data), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__chunk__field_indices_by_name[] = { + 3, /* field[3] = data */ + 1, /* field[1] = max_time_ms */ + 0, /* field[0] = min_time_ms */ + 2, /* field[2] = type */ +}; +static const ProtobufCIntRange prometheus__chunk__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor prometheus__chunk__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.Chunk", + "Chunk", + "Prometheus__Chunk", + "prometheus", + sizeof(Prometheus__Chunk), + 4, + prometheus__chunk__field_descriptors, + prometheus__chunk__field_indices_by_name, + 1, prometheus__chunk__number_ranges, + (ProtobufCMessageInit) prometheus__chunk__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__chunked_series__field_descriptors[2] = +{ + { + "labels", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__ChunkedSeries, n_labels), + offsetof(Prometheus__ChunkedSeries, labels), + &prometheus__label__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "chunks", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__ChunkedSeries, n_chunks), + offsetof(Prometheus__ChunkedSeries, chunks), + &prometheus__chunk__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__chunked_series__field_indices_by_name[] = { + 1, /* field[1] = chunks */ + 0, /* field[0] = labels */ +}; +static const ProtobufCIntRange prometheus__chunked_series__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__chunked_series__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.ChunkedSeries", + "ChunkedSeries", + "Prometheus__ChunkedSeries", + "prometheus", + sizeof(Prometheus__ChunkedSeries), + 2, + prometheus__chunked_series__field_descriptors, + prometheus__chunked_series__field_indices_by_name, + 1, prometheus__chunked_series__number_ranges, + (ProtobufCMessageInit) prometheus__chunked_series__init, + NULL,NULL,NULL /* reserved[123] */ +}; |