summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/cmetrics/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--fluent-bit/lib/cmetrics/src/CMakeLists.txt80
-rw-r--r--fluent-bit/lib/cmetrics/src/cmetrics.c147
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_atomic_clang.c42
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_atomic_gcc.c42
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_atomic_generic.c123
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_atomic_msvc.c131
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_cat.c454
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_counter.c180
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_decode_msgpack.c1474
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_decode_opentelemetry.c1289
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.c1160
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.l195
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_decode_prometheus.y151
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_encode_influx.c374
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_encode_msgpack.c552
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_encode_opentelemetry.c2592
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_encode_prometheus.c543
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_encode_prometheus_remote_write.c1131
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_encode_splunk_hec.c710
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_encode_text.c332
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_gauge.c198
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_histogram.c403
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_label.c100
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_log.c91
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_map.c318
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_metric.c142
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_metric_histogram.c192
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_mpack_utils.c286
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_opts.c118
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_summary.c306
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_time.c34
-rw-r--r--fluent-bit/lib/cmetrics/src/cmt_untyped.c140
-rw-r--r--fluent-bit/lib/cmetrics/src/external/LICENSE32
-rw-r--r--fluent-bit/lib/cmetrics/src/external/opentelemetry_common.pb-c.c624
-rw-r--r--fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics.pb-c.c1996
-rw-r--r--fluent-bit/lib/cmetrics/src/external/opentelemetry_metrics_service.pb-c.c189
-rw-r--r--fluent-bit/lib/cmetrics/src/external/opentelemetry_resource.pb-c.c105
-rw-r--r--fluent-bit/lib/cmetrics/src/external/protobuf-c.c3667
-rw-r--r--fluent-bit/lib/cmetrics/src/external/remote.pb-c.c615
-rw-r--r--fluent-bit/lib/cmetrics/src/external/types.pb-c.c1092
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, &timestamp);
+ 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, &timestamp);
+ 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, &timestamp);
+ 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, &timestamp);
+
+ 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, &timestamp);
+
+ 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, &timestamp);
+
+ 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, &timestamp);
+
+ 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, &timestamp);
+
+ 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, &timestamp);
+
+ 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] */
+};