summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/ctraces/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:22 +0000
commitc21c3b0befeb46a51b6bf3758ffa30813bea0ff0 (patch)
tree9754ff1ca740f6346cf8483ec915d4054bc5da2d /fluent-bit/lib/ctraces/src
parentAdding upstream version 1.43.2. (diff)
downloadnetdata-c21c3b0befeb46a51b6bf3758ffa30813bea0ff0.tar.xz
netdata-c21c3b0befeb46a51b6bf3758ffa30813bea0ff0.zip
Adding upstream version 1.44.3.upstream/1.44.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/lib/ctraces/src')
-rw-r--r--fluent-bit/lib/ctraces/src/CMakeLists.txt39
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_attributes.c88
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_decode_msgpack.c715
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_decode_opentelemetry.c593
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_encode_msgpack.c528
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_encode_opentelemetry.c1322
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_encode_text.c449
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_id.c255
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_link.c142
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_log.c88
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_mpack_utils.c488
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_random.c86
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_resource.c159
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_scope.c129
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_span.c434
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_utils.c0
-rw-r--r--fluent-bit/lib/ctraces/src/ctr_version.c26
-rw-r--r--fluent-bit/lib/ctraces/src/ctraces.c72
18 files changed, 5613 insertions, 0 deletions
diff --git a/fluent-bit/lib/ctraces/src/CMakeLists.txt b/fluent-bit/lib/ctraces/src/CMakeLists.txt
new file mode 100644
index 000000000..5a6392464
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/CMakeLists.txt
@@ -0,0 +1,39 @@
+set(src
+ ctraces.c
+ ctr_resource.c
+ ctr_span.c
+ ctr_link.c
+ ctr_scope.c
+ ctr_log.c
+ ctr_id.c
+ ctr_random.c
+ ctr_utils.c
+ ctr_attributes.c
+ ctr_version.c
+ ctr_mpack_utils.c
+ # encoders
+ ctr_encode_text.c
+ ctr_encode_msgpack.c
+ ctr_encode_opentelemetry.c
+ # decoders
+ ctr_decode_msgpack.c
+ ctr_decode_opentelemetry.c
+ )
+
+# Static Library
+add_library(ctraces-static STATIC ${src})
+target_link_libraries(ctraces-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(ctraces-static PROPERTIES OUTPUT_NAME libctraces)
+else()
+ set_target_properties(ctraces-static PROPERTIES OUTPUT_NAME ctraces)
+endif(MSVC)
+
+install(TARGETS ctraces-static
+ RUNTIME DESTINATION ${CTR_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CTR_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CTR_INSTALL_LIBDIR}
+ COMPONENT library)
diff --git a/fluent-bit/lib/ctraces/src/ctr_attributes.c b/fluent-bit/lib/ctraces/src/ctr_attributes.c
new file mode 100644
index 000000000..44bb13853
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_attributes.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+struct ctrace_attributes *ctr_attributes_create()
+{
+ struct ctrace_attributes *attr;
+
+ attr = malloc(sizeof(struct ctrace_attributes));
+ if (!attr) {
+ ctr_errno();
+ return NULL;
+ }
+
+ attr->kv = cfl_kvlist_create(128);
+ if (!attr->kv) {
+ free(attr);
+ return NULL;
+ }
+
+ return attr;
+}
+
+void ctr_attributes_destroy(struct ctrace_attributes *attr)
+{
+ if (attr->kv) {
+ cfl_kvlist_destroy(attr->kv);
+ }
+ free(attr);
+}
+
+int ctr_attributes_count(struct ctrace_attributes *attr)
+{
+ return cfl_kvlist_count(attr->kv);
+}
+
+int ctr_attributes_set_string(struct ctrace_attributes *attr, char *key, char *value)
+{
+ return cfl_kvlist_insert_string(attr->kv, key, value);
+}
+
+int ctr_attributes_set_bool(struct ctrace_attributes *attr, char *key, int b)
+{
+ if (b != CTR_TRUE && b != CTR_FALSE) {
+ return -1;
+ }
+
+ return cfl_kvlist_insert_bool(attr->kv, key, b);
+}
+
+int ctr_attributes_set_int64(struct ctrace_attributes *attr, char *key, int64_t value)
+{
+ return cfl_kvlist_insert_int64(attr->kv, key, value);
+}
+
+int ctr_attributes_set_double(struct ctrace_attributes *attr, char *key, double value)
+{
+ return cfl_kvlist_insert_double(attr->kv, key, value);
+}
+
+int ctr_attributes_set_array(struct ctrace_attributes *attr, char *key,
+ struct cfl_array *value)
+{
+ return cfl_kvlist_insert_array(attr->kv, key, value);
+}
+
+int ctr_attributes_set_kvlist(struct ctrace_attributes *attr, char *key,
+ struct cfl_kvlist *value)
+{
+ return cfl_kvlist_insert_kvlist(attr->kv, key, value);
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_decode_msgpack.c b/fluent-bit/lib/ctraces/src/ctr_decode_msgpack.c
new file mode 100644
index 000000000..f1df5c325
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_decode_msgpack.c
@@ -0,0 +1,715 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 Eduardo Silva <eduardo@calyptia.com>
+ *
+ * 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 <ctraces/ctraces.h>
+#include <ctraces/ctr_mpack_utils.h>
+#include <ctraces/ctr_decode_msgpack.h>
+#include <cfl/cfl_sds.h>
+#include <ctraces/ctr_variant_utils.h>
+
+
+/* Resource callbacks */
+
+static int unpack_resource_dropped_attributes_count(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint32_tag(
+ reader, &context->resource->dropped_attr_count);
+}
+
+static int unpack_resource_attributes(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct cfl_kvlist *attributes;
+ int result;
+
+ if (ctr_mpack_peek_type(reader) == mpack_type_nil) {
+ result = ctr_mpack_consume_nil_tag(reader);
+ }
+ else {
+ result = unpack_cfl_kvlist(reader, &attributes);
+
+ if (result == 0) {
+ cfl_kvlist_destroy(context->resource->attr->kv);
+
+ context->resource->attr->kv = attributes;
+ }
+ }
+
+ return result;
+}
+
+static int unpack_resource(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"attributes", unpack_resource_attributes},
+ {"dropped_attributes_count", unpack_resource_dropped_attributes_count},
+ {NULL, NULL}
+ };
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+
+/* Instrumentation scope callbacks */
+
+static int unpack_instrumentation_scope_name(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_string_or_nil_tag(
+ reader,
+ &context->scope_span->instrumentation_scope->name);
+}
+
+static int unpack_instrumentation_scope_version(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_string_or_nil_tag(
+ reader,
+ &context->scope_span->instrumentation_scope->version);
+}
+
+static int unpack_instrumentation_scope_dropped_attribute_count(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint32_tag(
+ reader,
+ &context->scope_span->instrumentation_scope->dropped_attr_count);
+}
+
+static int unpack_instrumentation_scope_attributes(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctrace_attributes *attributes;
+ int result;
+
+ if (ctr_mpack_peek_type(reader) == mpack_type_nil) {
+ result = ctr_mpack_consume_nil_tag(reader);
+ }
+ else {
+ attributes = ctr_attributes_create();
+ if (attributes == NULL) {
+ return CTR_DECODE_MSGPACK_VARIANT_DECODE_ERROR;
+ }
+
+ cfl_kvlist_destroy(attributes->kv);
+
+ attributes->kv = NULL;
+
+ result = unpack_cfl_kvlist(reader, &attributes->kv);
+
+ if (result != 0) {
+ ctr_attributes_destroy(attributes);
+ return CTR_DECODE_MSGPACK_VARIANT_DECODE_ERROR;
+ }
+
+ context->scope_span->instrumentation_scope->attr = attributes;
+ }
+
+ return CTR_DECODE_MSGPACK_SUCCESS;
+}
+
+static int unpack_scope_span_instrumentation_scope(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctrace_instrumentation_scope *instrumentation_scope;
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"name", unpack_instrumentation_scope_name},
+ {"version", unpack_instrumentation_scope_version},
+ {"attributes", unpack_instrumentation_scope_attributes},
+ {"dropped_attributes_count", unpack_instrumentation_scope_dropped_attribute_count},
+ {NULL, NULL}
+ };
+
+ instrumentation_scope = ctr_instrumentation_scope_create(NULL, NULL, 0, NULL);
+
+ if (instrumentation_scope == NULL) {
+ return CTR_DECODE_MSGPACK_ALLOCATION_ERROR;
+ }
+
+ ctr_scope_span_set_instrumentation_scope(context->scope_span, instrumentation_scope);
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+/* Event callbacks */
+
+static int unpack_event_name(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ if (context->event->name != NULL) {
+ cfl_sds_destroy(context->event->name);
+
+ context->event->name = NULL;
+ }
+
+ return ctr_mpack_consume_string_or_nil_tag(reader, &context->event->name);
+}
+
+static int unpack_event_time_unix_nano(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint64_tag(reader, &context->event->time_unix_nano);
+}
+
+static int unpack_event_attributes(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct cfl_kvlist *attributes;
+ int result;
+
+ if (ctr_mpack_peek_type(reader) == mpack_type_nil) {
+ ctr_mpack_consume_nil_tag(reader);
+
+ return CTR_DECODE_MSGPACK_SUCCESS;
+ }
+
+ result = unpack_cfl_kvlist(reader, &attributes);
+
+ if (result != 0) {
+ return CTR_DECODE_MSGPACK_VARIANT_DECODE_ERROR;
+ }
+
+ cfl_kvlist_destroy(context->event->attr->kv);
+ context->event->attr->kv = attributes;
+
+ return CTR_DECODE_MSGPACK_SUCCESS;
+}
+
+static int unpack_event_dropped_attributes_count(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint32_tag(reader, &context->event->dropped_attr_count);
+}
+
+static int unpack_event(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"name", unpack_event_name},
+ {"time_unix_nano", unpack_event_time_unix_nano},
+ {"attributes", unpack_event_attributes},
+ {"dropped_attributes_count", unpack_event_dropped_attributes_count},
+ {NULL, NULL}
+ };
+
+ context->event = ctr_span_event_add(context->span, "");
+
+ if (context->event == NULL) {
+ return CTR_DECODE_MSGPACK_ALLOCATION_ERROR;
+ }
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+/* Link callbacks */
+
+static int unpack_link_trace_id(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ int result;
+ cfl_sds_t value;
+
+ result = ctr_mpack_consume_string_or_nil_tag(reader, &value);
+
+ if (result == CTR_MPACK_SUCCESS && value != NULL) {
+ context->link->trace_id = ctr_id_from_base16(value);
+
+ if (context->link->trace_id == NULL) {
+ result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ cfl_sds_destroy(value);
+ }
+
+ return result;
+}
+
+static int unpack_link_span_id(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ int result;
+ cfl_sds_t value;
+
+ result = ctr_mpack_consume_string_or_nil_tag(reader, &value);
+
+ if (result == CTR_MPACK_SUCCESS && value != NULL) {
+ context->link->span_id = ctr_id_from_base16(value);
+
+ if (context->link->span_id == NULL) {
+ result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ cfl_sds_destroy(value);
+ }
+
+ return result;
+}
+
+static int unpack_link_trace_state(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_string_or_nil_tag(reader, &context->link->trace_state);
+}
+
+static int unpack_link_dropped_attributes_count(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint32_tag(reader, &context->link->dropped_attr_count);
+}
+
+static int unpack_link_attributes(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct cfl_kvlist *attributes;
+ int result;
+
+ if (ctr_mpack_peek_type(reader) == mpack_type_nil) {
+ result = ctr_mpack_consume_nil_tag(reader);
+ }
+ else {
+ result = unpack_cfl_kvlist(reader, &attributes);
+
+ if (result == 0) {
+ if (context->link->attr == NULL) {
+ context->link->attr = ctr_attributes_create();
+ }
+
+ if (context->link->attr->kv != NULL) {
+ cfl_kvlist_destroy(context->link->attr->kv);
+ }
+
+ context->link->attr->kv = attributes;
+
+ result = CTR_DECODE_MSGPACK_SUCCESS;
+ }
+ else {
+ result = CTR_DECODE_MSGPACK_VARIANT_DECODE_ERROR;
+ }
+ }
+
+ return result;
+}
+
+static int unpack_link(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"trace_id", unpack_link_trace_id},
+ {"span_id", unpack_link_span_id},
+ {"trace_state", unpack_link_trace_state},
+ {"attributes", unpack_link_attributes},
+ {"dropped_attributes_count", unpack_link_dropped_attributes_count},
+ {NULL, NULL}
+ };
+
+ context->link = ctr_link_create(context->span, NULL, 0, NULL, 0);
+
+ if (context->link == NULL) {
+ return CTR_MPACK_ALLOCATION_ERROR;
+ }
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+/* Span callbacks */
+
+static int unpack_span_trace_id(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctrace_id *decoded_id;
+ int result;
+ cfl_sds_t value;
+
+ result = ctr_mpack_consume_string_or_nil_tag(reader, &value);
+
+ if (result == CTR_MPACK_SUCCESS && value != NULL) {
+ decoded_id = ctr_id_from_base16(value);
+
+ if (decoded_id != NULL) {
+ ctr_span_set_trace_id_with_cid(context->span, decoded_id);
+
+ ctr_id_destroy(decoded_id);
+ }
+ else {
+ result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ cfl_sds_destroy(value);
+ }
+
+ return result;
+}
+
+static int unpack_span_span_id(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctrace_id *decoded_id;
+ int result;
+ cfl_sds_t value;
+
+ result = ctr_mpack_consume_string_or_nil_tag(reader, &value);
+
+ if (result == CTR_MPACK_SUCCESS && value != NULL) {
+ decoded_id = ctr_id_from_base16(value);
+
+ if (decoded_id != NULL) {
+ ctr_span_set_span_id_with_cid(context->span, decoded_id);
+
+ ctr_id_destroy(decoded_id);
+ }
+ else {
+ result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ cfl_sds_destroy(value);
+ }
+
+ return result;
+}
+
+static int unpack_span_parent_span_id(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctrace_id *decoded_id;
+ int result;
+ cfl_sds_t value;
+
+ result = ctr_mpack_consume_string_or_nil_tag(reader, &value);
+
+ if (result == CTR_MPACK_SUCCESS && value != NULL) {
+ decoded_id = ctr_id_from_base16(value);
+
+ if (decoded_id != NULL) {
+ ctr_span_set_parent_span_id_with_cid(context->span, decoded_id);
+
+ ctr_id_destroy(decoded_id);
+ }
+ else {
+ result = CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ cfl_sds_destroy(value);
+ }
+
+ return result;
+}
+
+static int unpack_span_trace_state(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ if (context->span->trace_state != NULL) {
+ cfl_sds_destroy(context->span->trace_state);
+
+ context->span->trace_state = NULL;
+ }
+
+ return ctr_mpack_consume_string_or_nil_tag(reader, &context->span->trace_state);
+}
+
+static int unpack_span_name(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ if (context->span->name != NULL) {
+ cfl_sds_destroy(context->span->name);
+
+ context->span->name = NULL;
+ }
+
+ return ctr_mpack_consume_string_or_nil_tag(reader, &context->span->name);
+}
+
+static int unpack_span_kind(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_int32_tag(reader, &context->span->kind);
+}
+
+static int unpack_span_start_time_unix_nano(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint64_tag(reader, &context->span->start_time_unix_nano);
+}
+
+static int unpack_span_end_time_unix_nano(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint64_tag(reader, &context->span->end_time_unix_nano);
+}
+
+static int unpack_span_attributes(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct cfl_kvlist *attributes;
+ int result;
+
+ if (ctr_mpack_peek_type(reader) == mpack_type_nil) {
+ ctr_mpack_consume_nil_tag(reader);
+
+ return CTR_DECODE_MSGPACK_SUCCESS;
+ }
+
+ result = unpack_cfl_kvlist(reader, &attributes);
+
+ if (result != 0) {
+ return CTR_DECODE_MSGPACK_VARIANT_DECODE_ERROR;
+ }
+
+ cfl_kvlist_destroy(context->span->attr->kv);
+ context->span->attr->kv = attributes;
+
+ return CTR_DECODE_MSGPACK_SUCCESS;
+}
+
+static int unpack_span_dropped_attributes_count(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_uint32_tag(reader, &context->span->dropped_attr_count);
+}
+
+static int unpack_span_events(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ return ctr_mpack_unpack_array(reader, unpack_event, ctx);
+}
+
+
+static int unpack_span_links(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ return ctr_mpack_unpack_array(reader, unpack_link, ctx);
+}
+
+static int unpack_span_status_code(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_int32_tag(reader, &context->span->status.code);
+}
+
+static int unpack_span_status_message(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ return ctr_mpack_consume_string_or_nil_tag(reader, &context->span->status.message);
+}
+
+static int unpack_span_status(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"code", unpack_span_status_code},
+ {"message", unpack_span_status_message},
+ {NULL, NULL}
+ };
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+static int unpack_span(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"trace_id", unpack_span_trace_id},
+ {"span_id", unpack_span_span_id},
+ {"parent_span_id", unpack_span_parent_span_id},
+ {"trace_state", unpack_span_trace_state},
+ {"name", unpack_span_name},
+ {"kind", unpack_span_kind},
+ {"start_time_unix_nano", unpack_span_start_time_unix_nano},
+ {"end_time_unix_nano", unpack_span_end_time_unix_nano},
+ {"attributes", unpack_span_attributes},
+ {"dropped_attributes_count", unpack_span_dropped_attributes_count},
+ {"events", unpack_span_events},
+ {"links", unpack_span_links},
+ {"status", unpack_span_status},
+ {NULL, NULL}
+ };
+
+ context->span = ctr_span_create(context->trace, context->scope_span, "", NULL);
+
+ if (context->span == NULL) {
+ return CTR_DECODE_MSGPACK_ALLOCATION_ERROR;
+ }
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+/* Scope span callbacks */
+
+static int unpack_scope_span_spans(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ return ctr_mpack_unpack_array(reader, unpack_span, ctx);
+}
+
+static int unpack_scope_span_schema_url(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ if (context->scope_span->schema_url != NULL) {
+ cfl_sds_destroy(context->scope_span->schema_url);
+
+ context->scope_span->schema_url = NULL;
+ }
+
+ return ctr_mpack_consume_string_or_nil_tag(reader, &context->scope_span->schema_url);
+}
+
+static int unpack_scope_span(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"scope", unpack_scope_span_instrumentation_scope},
+ {"spans", unpack_scope_span_spans},
+ {"schema_url", unpack_scope_span_schema_url},
+ {NULL, NULL}
+ };
+
+ context->scope_span = ctr_scope_span_create(context->resource_span);
+
+ if (context->scope_span == NULL) {
+ return CTR_DECODE_MSGPACK_ALLOCATION_ERROR;
+ }
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+/* Resource span callbacks */
+
+static int unpack_resource_span_scope_spans(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ return ctr_mpack_unpack_array(reader, unpack_scope_span, ctx);
+}
+
+static int unpack_resource_span_schema_url(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+
+ if (context->resource_span->schema_url != NULL) {
+ cfl_sds_destroy(context->resource_span->schema_url);
+
+ context->resource_span->schema_url = NULL;
+ }
+
+ return ctr_mpack_consume_string_or_nil_tag(reader, &context->resource_span->schema_url);
+}
+
+static int unpack_resource_span(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ struct ctr_msgpack_decode_context *context = ctx;
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"resource", unpack_resource},
+ {"schema_url", unpack_resource_span_schema_url},
+ {"scope_spans", unpack_resource_span_scope_spans},
+ {NULL, NULL}
+ };
+
+ context->resource_span = ctr_resource_span_create(context->trace);
+
+ if (context->resource_span == NULL) {
+ return CTR_DECODE_MSGPACK_ALLOCATION_ERROR;
+ }
+
+ context->resource = context->resource_span->resource;
+
+ return ctr_mpack_unpack_map(reader, callbacks, ctx);
+}
+
+/* Outermost block callbacks*/
+
+static int unpack_resource_spans(mpack_reader_t *reader, size_t index, void *ctx)
+{
+ return ctr_mpack_unpack_array(reader, unpack_resource_span, ctx);
+}
+
+static int unpack_context(mpack_reader_t *reader, struct ctr_msgpack_decode_context *ctx)
+{
+ struct ctr_mpack_map_entry_callback_t callbacks[] = \
+ {
+ {"resourceSpans", unpack_resource_spans},
+ {NULL, NULL}
+ };
+
+ return ctr_mpack_unpack_map(reader, callbacks, (void *) ctx);
+}
+
+int ctr_decode_msgpack_create(struct ctrace **out_context, char *in_buf, size_t in_size, size_t *offset)
+{
+ size_t remainder;
+ struct ctr_msgpack_decode_context context;
+ mpack_reader_t reader;
+ int result;
+
+ memset(&context, 0, sizeof(context));
+
+ context.trace = ctr_create(NULL);
+
+ if (context.trace == NULL) {
+ return -1;
+ }
+
+ in_size -= *offset;
+
+ mpack_reader_init_data(&reader, &in_buf[*offset], in_size);
+
+ result = unpack_context(&reader, &context);
+
+ remainder = mpack_reader_remaining(&reader, NULL);
+
+ *offset += in_size - remainder;
+
+ mpack_reader_destroy(&reader);
+
+ if (result != CTR_DECODE_MSGPACK_SUCCESS) {
+ ctr_destroy(context.trace);
+
+ context.trace = NULL;
+ }
+
+ *out_context = context.trace;
+
+ return result;
+}
+
+void ctr_decode_msgpack_destroy(struct ctrace *context)
+{
+ if (context != NULL) {
+ ctr_destroy(context);
+ }
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_decode_opentelemetry.c b/fluent-bit/lib/ctraces/src/ctr_decode_opentelemetry.c
new file mode 100644
index 000000000..139ae2cd9
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_decode_opentelemetry.c
@@ -0,0 +1,593 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+#include <cfl/cfl_array.h>
+#include <fluent-otel-proto/fluent-otel.h>
+
+static int convert_any_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type, char *key,
+ Opentelemetry__Proto__Common__V1__AnyValue *val);
+
+static int convert_string_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type,
+ char *key, char *val)
+{
+ int result;
+
+ result = -2;
+
+ switch (value_type) {
+
+ case CTR_OPENTELEMETRY_TYPE_ATTRIBUTE:
+ result = ctr_attributes_set_string(ctr_val->ctr_attr, key, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_ARRAY:
+ result = cfl_array_append_string(ctr_val->cfl_arr, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_KVLIST:
+ result = cfl_kvlist_insert_string(ctr_val->cfl_kvlist, key, val);
+ break;
+
+ }
+
+ if (result == -2) {
+ printf("convert_string_value: unknown value type");
+ }
+
+ return result;
+}
+
+static int convert_bool_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type,
+ char *key, protobuf_c_boolean val)
+{
+ int result;
+
+ result = -2;
+
+ switch (value_type) {
+
+ case CTR_OPENTELEMETRY_TYPE_ATTRIBUTE:
+ result = ctr_attributes_set_bool(ctr_val->ctr_attr, key, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_ARRAY:
+ result = cfl_array_append_bool(ctr_val->cfl_arr, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_KVLIST:
+ result = cfl_kvlist_insert_bool(ctr_val->cfl_kvlist, key, val);
+ break;
+
+ }
+
+ if (result == -2) {
+ printf("convert_bool_value: unknown value type");
+ }
+
+ return result;
+}
+
+static int convert_int_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type,
+ char *key, int64_t val)
+{
+ int result;
+
+ result = -2;
+
+ switch (value_type) {
+
+ case CTR_OPENTELEMETRY_TYPE_ATTRIBUTE:
+ result = ctr_attributes_set_int64(ctr_val->ctr_attr, key, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_ARRAY:
+ result = cfl_array_append_int64(ctr_val->cfl_arr, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_KVLIST:
+ result = cfl_kvlist_insert_int64(ctr_val->cfl_kvlist, key, val);
+ break;
+
+ }
+
+ if (result == -2) {
+ printf("convert_int_value: unknown value type");
+ }
+
+ return result;
+}
+
+static int convert_double_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type,
+ char *key, double val)
+{
+ int result;
+
+ result = -2;
+
+ switch (value_type) {
+
+ case CTR_OPENTELEMETRY_TYPE_ATTRIBUTE:
+ result = ctr_attributes_set_double(ctr_val->ctr_attr, key, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_ARRAY:
+ result = cfl_array_append_double(ctr_val->cfl_arr, val);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_KVLIST:
+ result = cfl_kvlist_insert_double(ctr_val->cfl_kvlist, key, val);
+ break;
+
+ }
+
+ if (result == -2) {
+ printf("convert_double_value: unknown value type");
+ }
+
+ return result;
+}
+
+static int convert_array_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type,
+ char *key, Opentelemetry__Proto__Common__V1__ArrayValue *otel_arr)
+{
+ int array_index;
+ int result;
+ struct opentelemetry_decode_value *ctr_arr_val;
+ Opentelemetry__Proto__Common__V1__AnyValue *val;
+
+ ctr_arr_val = malloc(sizeof(struct opentelemetry_decode_value));
+ if (!ctr_arr_val) {
+ ctr_errno();
+ return -1;
+ }
+ ctr_arr_val->cfl_arr = cfl_array_create(otel_arr->n_values);
+
+ result = 0;
+
+ for (array_index = 0;
+ array_index < otel_arr->n_values && result == 0;
+ array_index++) {
+ val = otel_arr->values[array_index];
+ result = convert_any_value(ctr_arr_val, CTR_OPENTELEMETRY_TYPE_ARRAY, NULL, val);
+ }
+
+ if (result < 0) {
+ cfl_array_destroy(ctr_arr_val->cfl_arr);
+ free(ctr_arr_val);
+ return result;
+ }
+
+ result = -2;
+
+ switch (value_type) {
+
+ case CTR_OPENTELEMETRY_TYPE_ATTRIBUTE:
+ result = ctr_attributes_set_array(ctr_val->ctr_attr, key, ctr_arr_val->cfl_arr);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_ARRAY:
+ result = cfl_array_append_array(ctr_val->cfl_arr, ctr_arr_val->cfl_arr);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_KVLIST:
+ result = cfl_kvlist_insert_array(ctr_val->cfl_kvlist, key, ctr_arr_val->cfl_arr);
+ break;
+
+ }
+
+ free(ctr_arr_val);
+ if (result == -2) {
+ fprintf(stderr, "convert_array_value: unknown value type\n");
+ }
+
+ return result;
+}
+
+static int convert_kvlist_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type,
+ char *key, Opentelemetry__Proto__Common__V1__KeyValueList *otel_kvlist)
+{
+ int kvlist_index;
+ int result;
+ struct opentelemetry_decode_value *ctr_kvlist_val;
+ Opentelemetry__Proto__Common__V1__KeyValue *kv;
+
+ ctr_kvlist_val = malloc(sizeof(struct opentelemetry_decode_value));
+ if (!ctr_kvlist_val) {
+ ctr_errno();
+ return -1;
+ }
+ ctr_kvlist_val->cfl_kvlist = cfl_kvlist_create();
+
+ result = 0;
+ for (kvlist_index = 0;
+ kvlist_index < otel_kvlist->n_values && result ==0;
+ kvlist_index++) {
+
+ kv = otel_kvlist->values[kvlist_index];
+ result = convert_any_value(ctr_kvlist_val, CTR_OPENTELEMETRY_TYPE_KVLIST, kv->key, kv->value);
+ }
+
+ if (result < 0){
+ cfl_kvlist_destroy(ctr_kvlist_val->cfl_kvlist);
+ free(ctr_kvlist_val);
+ return result;
+ }
+
+ result = -2;
+
+ switch (value_type) {
+
+ case CTR_OPENTELEMETRY_TYPE_ATTRIBUTE:
+ result = ctr_attributes_set_kvlist(ctr_val->ctr_attr, key, ctr_kvlist_val->cfl_kvlist);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_ARRAY:
+ result = cfl_array_append_kvlist(ctr_val->cfl_arr, ctr_kvlist_val->cfl_kvlist);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_KVLIST:
+ result = cfl_kvlist_insert_kvlist(ctr_val->cfl_kvlist, key, ctr_kvlist_val->cfl_kvlist);
+ break;
+
+ }
+
+ free(ctr_kvlist_val);
+
+ if (result == -2) {
+ printf("convert_kvlist_value: unknown value type");
+ }
+
+ return result;
+}
+
+static int convert_bytes_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type,
+ char *key, void *buf, size_t len)
+{
+ int result;
+
+ result = -2;
+
+ switch (value_type) {
+ case CTR_OPENTELEMETRY_TYPE_ATTRIBUTE:
+ result = -1;
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_ARRAY:
+ result = cfl_array_append_bytes(ctr_val->cfl_arr, buf, len);
+ break;
+
+ case CTR_OPENTELEMETRY_TYPE_KVLIST:
+ result = cfl_kvlist_insert_bytes(ctr_val->cfl_kvlist, key, buf, len);
+ break;
+
+ }
+
+ if (result == -2) {
+ printf("convert_bytes_value: unknown value type");
+ }
+
+ return result;
+}
+
+static int convert_any_value(struct opentelemetry_decode_value *ctr_val,
+ opentelemetry_decode_value_type value_type, char *key,
+ Opentelemetry__Proto__Common__V1__AnyValue *val)
+{
+ int result;
+
+ switch (val->value_case) {
+
+ case OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_STRING_VALUE:
+ result = convert_string_value(ctr_val, value_type, key, val->string_value);
+ break;
+
+ case OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BOOL_VALUE:
+ result = convert_bool_value(ctr_val, value_type, key, val->bool_value);
+ break;
+
+ case OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_INT_VALUE:
+ result = convert_int_value(ctr_val, value_type, key, val->int_value);
+ break;
+
+ case OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_DOUBLE_VALUE:
+ result = convert_double_value(ctr_val, value_type, key, val->double_value);
+ break;
+
+ case OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_ARRAY_VALUE:
+ result = convert_array_value(ctr_val, value_type, key, val->array_value);
+ break;
+
+ case OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_KVLIST_VALUE:
+ result = convert_kvlist_value(ctr_val, value_type, key, val->kvlist_value);
+ break;
+
+ case OPENTELEMETRY__PROTO__COMMON__V1__ANY_VALUE__VALUE_BYTES_VALUE:
+ result = convert_bytes_value(ctr_val, value_type, key, val->bytes_value.data, val->bytes_value.len);
+ break;
+
+ default:
+ result = -1;
+ break;
+ }
+
+ return result;
+}
+
+static struct ctrace_attributes *convert_otel_attrs(size_t n_attributes,
+ Opentelemetry__Proto__Common__V1__KeyValue **otel_attr)
+{
+ int index_kv;
+ int result;
+ char *key;
+ struct opentelemetry_decode_value *ctr_decoded_attributes;
+ struct ctrace_attributes *attr;
+
+ Opentelemetry__Proto__Common__V1__KeyValue *kv;
+ Opentelemetry__Proto__Common__V1__AnyValue *val;
+
+ ctr_decoded_attributes = malloc(sizeof(struct opentelemetry_decode_value));
+ ctr_decoded_attributes->ctr_attr = ctr_attributes_create();
+
+ result = 0;
+
+ for (index_kv = 0; index_kv < n_attributes && result == 0; index_kv++) {
+ kv = otel_attr[index_kv];
+
+ key = kv->key;
+ val = kv->value;
+
+ result = convert_any_value(ctr_decoded_attributes,
+ CTR_OPENTELEMETRY_TYPE_ATTRIBUTE,
+ key, val);
+ }
+
+ if (result < 0) {
+ ctr_attributes_destroy(ctr_decoded_attributes->ctr_attr);
+ free(ctr_decoded_attributes);
+ return NULL;
+ }
+
+ attr = ctr_decoded_attributes->ctr_attr;
+ free(ctr_decoded_attributes);
+ return attr;
+}
+
+static int ctr_span_set_attributes(struct ctrace_span *span,
+ size_t n_attributes,
+ Opentelemetry__Proto__Common__V1__KeyValue **attributes)
+{
+ struct ctrace_attributes *ctr_attributes;
+
+ ctr_attributes = convert_otel_attrs(n_attributes, attributes);
+ if (ctr_attributes == NULL) {
+ return -1;
+ }
+
+ if (span->attr) {
+ ctr_attributes_destroy(span->attr);
+ }
+ span->attr = ctr_attributes;
+ return 0;
+}
+
+static int ctr_span_set_events(struct ctrace_span *span,
+ size_t n_events,
+ Opentelemetry__Proto__Trace__V1__Span__Event **events)
+{
+ int index_event;
+ struct ctrace_span_event *ctr_event;
+ struct ctrace_attributes *ctr_attributes;
+ Opentelemetry__Proto__Trace__V1__Span__Event *event;
+
+ cfl_list_init(&span->events);
+
+ for (index_event = 0; index_event < n_events; index_event++) {
+ event = events[index_event];
+
+ ctr_event = ctr_span_event_add_ts(span, event->name, event->time_unix_nano);
+
+ if (ctr_event == NULL) {
+ return -1;
+ }
+
+ ctr_attributes = convert_otel_attrs(event->n_attributes, event->attributes);
+
+ if (ctr_attributes == NULL) {
+ return -1;
+ }
+
+ if (ctr_event->attr) {
+ ctr_attributes_destroy(ctr_event->attr);
+ }
+
+ ctr_event->attr = ctr_attributes;
+ ctr_span_event_set_dropped_attributes_count(ctr_event, event->dropped_attributes_count);
+ }
+
+ return 0;
+}
+
+static int resource_set_data(struct ctrace_resource *resource,
+ Opentelemetry__Proto__Resource__V1__Resource *otel_resource)
+{
+ struct ctrace_attributes *attributes;
+
+ attributes = convert_otel_attrs(otel_resource->n_attributes, otel_resource->attributes);
+
+ if (attributes == NULL) {
+ return -1;
+ }
+
+ ctr_resource_set_attributes(resource, attributes);
+ ctr_resource_set_dropped_attr_count(resource, otel_resource->dropped_attributes_count);
+
+ return 0;
+}
+
+void ctr_scope_span_set_scope(struct ctrace_scope_span *scope_span,
+ Opentelemetry__Proto__Common__V1__InstrumentationScope *scope)
+{
+ struct ctrace_attributes *ctr_attributes;
+ struct ctrace_instrumentation_scope *ins_scope;
+
+ ctr_attributes = convert_otel_attrs(scope->n_attributes, scope->attributes);
+ if (ctr_attributes == NULL) {
+ return;
+ }
+
+ ins_scope = ctr_instrumentation_scope_create(scope->name, scope->version,
+ scope->dropped_attributes_count,
+ ctr_attributes);
+ if (!ins_scope) {
+ ctr_attributes_destroy(ctr_attributes);
+ return;
+ }
+
+ ctr_scope_span_set_instrumentation_scope(scope_span, ins_scope);
+}
+
+void ctr_span_set_links(struct ctrace_span *ctr_span, size_t n_links,
+ Opentelemetry__Proto__Trace__V1__Span__Link **links)
+{
+ int index_link;
+ struct ctrace_link *ctr_link;
+ struct ctrace_attributes *ctr_attributes;
+ Opentelemetry__Proto__Trace__V1__Span__Link *link;
+
+ for (index_link = 0; index_link < n_links; index_link++) {
+ link = links[index_link];
+
+ ctr_link = ctr_link_create(ctr_span,
+ link->trace_id.data, link->trace_id.len,
+ link->span_id.data, link->span_id.len);
+
+ if (ctr_link == NULL) {
+ return;
+ }
+
+ ctr_attributes = convert_otel_attrs(link->n_attributes, link->attributes);
+
+ if (ctr_attributes == NULL) {
+ return;
+ }
+
+ ctr_link->attr = ctr_attributes;
+ ctr_link_set_dropped_attr_count(ctr_link, link->dropped_attributes_count);
+ }
+
+}
+
+int ctr_decode_opentelemetry_create(struct ctrace **out_ctr,
+ char *in_buf,
+ size_t in_size, size_t *offset)
+{
+ size_t resource_span_index;
+ size_t scope_span_index;
+ size_t span_index;
+ struct ctrace *ctr;
+ struct ctrace_span *span;
+ struct ctrace_resource *resource;
+ struct ctrace_resource_span *resource_span;
+ struct ctrace_scope_span *scope_span;
+
+ Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest *service_request;
+ Opentelemetry__Proto__Trace__V1__ResourceSpans *otel_resource_span;
+ Opentelemetry__Proto__Trace__V1__ScopeSpans *otel_scope_span;
+ Opentelemetry__Proto__Trace__V1__Span *otel_span;
+
+ service_request = opentelemetry__proto__collector__trace__v1__export_trace_service_request__unpack(NULL,
+ in_size - *offset,
+ (unsigned char *) &in_buf[*offset]);
+ if (service_request == NULL) {
+ return -1;
+ }
+
+ ctr = ctr_create(NULL);
+
+ for (resource_span_index = 0; resource_span_index < service_request->n_resource_spans; resource_span_index++) {
+ otel_resource_span = service_request->resource_spans[resource_span_index];
+ if (otel_resource_span == NULL) {
+ opentelemetry__proto__collector__trace__v1__export_trace_service_request__free_unpacked(service_request, NULL);
+ return -1;
+ }
+
+ /* resource span */
+ resource_span = ctr_resource_span_create(ctr);
+ ctr_resource_span_set_schema_url(resource_span, otel_resource_span->schema_url);
+
+ /* resource */
+ resource = ctr_resource_span_get_resource(resource_span);
+ resource_set_data(resource, otel_resource_span->resource);
+
+ for (scope_span_index = 0; scope_span_index < otel_resource_span->n_scope_spans; scope_span_index++) {
+ otel_scope_span = otel_resource_span->scope_spans[scope_span_index];
+ if (otel_scope_span == NULL) {
+ opentelemetry__proto__collector__trace__v1__export_trace_service_request__free_unpacked(service_request, NULL);
+ return -1;
+ }
+
+ scope_span = ctr_scope_span_create(resource_span);
+ ctr_scope_span_set_schema_url(scope_span, otel_scope_span->schema_url);
+ ctr_scope_span_set_scope(scope_span, otel_scope_span->scope);
+
+ for (span_index = 0; span_index < otel_scope_span->n_spans; span_index++) {
+ otel_span = otel_scope_span->spans[span_index];
+ if (otel_span == NULL) {
+ opentelemetry__proto__collector__trace__v1__export_trace_service_request__free_unpacked(service_request, NULL);
+ return -1;
+ }
+
+ span = ctr_span_create(ctr, scope_span, otel_span->name, NULL);
+
+ /* copy data from otel span to ctraces span representation */
+ ctr_span_set_trace_id(span, otel_span->trace_id.data, otel_span->trace_id.len);
+ ctr_span_set_span_id(span, otel_span->span_id.data, otel_span->span_id.len);
+ ctr_span_set_parent_span_id(span, otel_span->parent_span_id.data, otel_span->parent_span_id.len);
+ ctr_span_kind_set(span, otel_span->kind);
+ ctr_span_start_ts(ctr, span, otel_span->start_time_unix_nano);
+ ctr_span_end_ts(ctr, span, otel_span->end_time_unix_nano);
+ ctr_span_set_status(span, otel_span->status->code, otel_span->status->message);
+ ctr_span_set_attributes(span, otel_span->n_attributes, otel_span->attributes);
+ ctr_span_set_events(span, otel_span->n_events, otel_span->events);
+ ctr_span_set_dropped_attributes_count(span, otel_span->dropped_attributes_count);
+ ctr_span_set_dropped_events_count(span, otel_span->dropped_events_count);
+ ctr_span_set_links(span, otel_span->n_links, otel_span->links);
+ }
+ }
+ }
+
+ opentelemetry__proto__collector__trace__v1__export_trace_service_request__free_unpacked(service_request, NULL);
+ *out_ctr = ctr;
+
+ return 0;
+}
+
+void ctr_decode_opentelemetry_destroy(struct ctrace *ctr)
+{
+ ctr_destroy(ctr);
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_encode_msgpack.c b/fluent-bit/lib/ctraces/src/ctr_encode_msgpack.c
new file mode 100644
index 000000000..bd3d187bf
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_encode_msgpack.c
@@ -0,0 +1,528 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+/* local declarations */
+static void pack_variant(mpack_writer_t *writer, struct cfl_variant *variant);
+
+static void pack_bool(mpack_writer_t *writer, int b)
+{
+ if (b) {
+ mpack_write_true(writer);
+ }
+ else {
+ mpack_write_false(writer);
+ }
+}
+
+static void pack_string(mpack_writer_t *writer, cfl_sds_t str)
+{
+ mpack_write_str(writer, str, cfl_sds_len(str));
+}
+
+static void pack_int64(mpack_writer_t *writer, int64_t val)
+{
+ mpack_write_i64(writer, val);
+}
+
+static void pack_double(mpack_writer_t *writer, double val)
+{
+ mpack_write_double(writer, val);
+}
+
+static void pack_array(mpack_writer_t *writer, struct cfl_array *array)
+{
+ int i;
+ struct cfl_variant *entry;
+
+ mpack_start_array(writer, array->entry_count);
+
+ for (i = 0; i < array->entry_count; i++) {
+ entry = array->entries[i];
+ pack_variant(writer, entry);
+ }
+ mpack_finish_array(writer);
+}
+
+static void pack_kvlist(mpack_writer_t *writer, struct cfl_kvlist *kvlist)
+{
+ int count;
+ struct cfl_list *head;
+ struct cfl_list *list;
+ struct cfl_kvpair *kvpair;
+
+ list = &kvlist->list;
+ count = cfl_list_size(list);
+
+ mpack_start_map(writer, count);
+
+ cfl_list_foreach(head, list) {
+ kvpair = cfl_list_entry(head, struct cfl_kvpair, _head);
+
+ /* key */
+ mpack_write_str(writer, kvpair->key, cfl_sds_len(kvpair->key));
+
+ /* value */
+ pack_variant(writer, kvpair->val);
+ }
+ mpack_finish_map(writer);
+}
+
+static void pack_bytes(mpack_writer_t *writer, cfl_sds_t bytes)
+{
+ size_t len;
+
+ len = cfl_sds_len(bytes);
+
+ // mpack_start_bin(writer, len);
+ mpack_write_bin(writer, bytes, len);
+ // mpack_finish_bin(writer);
+}
+
+static void pack_variant(mpack_writer_t *writer, struct cfl_variant *variant)
+{
+ int type = variant->type;
+
+ if (type == CFL_VARIANT_STRING) {
+ pack_string(writer, variant->data.as_string);
+ }
+ else if (type == CFL_VARIANT_BOOL) {
+ pack_bool(writer, variant->data.as_bool);
+ }
+ else if (type == CFL_VARIANT_INT) {
+ pack_int64(writer, variant->data.as_int64);
+ }
+ else if (type == CFL_VARIANT_DOUBLE) {
+ pack_double(writer, variant->data.as_double);
+ }
+ else if (type == CFL_VARIANT_ARRAY) {
+ pack_array(writer, variant->data.as_array);
+ }
+ else if (type == CFL_VARIANT_KVLIST) {
+ pack_kvlist(writer, variant->data.as_kvlist);
+ }
+ else if (type == CFL_VARIANT_BYTES) {
+ pack_bytes(writer, variant->data.as_bytes);
+ }
+ else if (type == CFL_VARIANT_REFERENCE) {
+ /* unsupported */
+ }
+}
+
+static void pack_attributes(mpack_writer_t *writer, struct ctrace_attributes *attr)
+{
+ struct cfl_kvlist *kvlist;
+
+ kvlist = attr->kv;
+ pack_kvlist(writer, kvlist);
+}
+
+static void pack_instrumentation_scope(mpack_writer_t *writer, struct ctrace_instrumentation_scope *ins_scope)
+{
+ mpack_start_map(writer, 4);
+
+ /* name */
+ mpack_write_cstr(writer, "name");
+ if (ins_scope->name) {
+ mpack_write_str(writer, ins_scope->name, cfl_sds_len(ins_scope->name));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* version */
+ mpack_write_cstr(writer, "version");
+ if (ins_scope->version) {
+ mpack_write_str(writer, ins_scope->version, cfl_sds_len(ins_scope->version));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* attributes */
+ mpack_write_cstr(writer, "attributes");
+ if (ins_scope->attr) {
+ pack_attributes(writer, ins_scope->attr);
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* dropped_attributes_count */
+ mpack_write_cstr(writer, "dropped_attributes_count");
+ mpack_write_u32(writer, ins_scope->dropped_attr_count);
+
+ /* finish */
+ mpack_finish_map(writer);
+}
+
+static void pack_id(mpack_writer_t *writer, struct ctrace_id *id)
+{
+ cfl_sds_t encoded_id;
+
+
+ if (id) {
+ encoded_id = ctr_id_to_lower_base16(id);
+
+ if (encoded_id != NULL) {
+ mpack_write_cstr(writer, encoded_id);
+
+ cfl_sds_destroy(encoded_id);
+ }
+ else {
+ /* we should be able to report this but at the moment
+ * we are not.
+ */
+
+ mpack_write_nil(writer);
+ }
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+}
+
+static void pack_events(mpack_writer_t *writer, struct cfl_list *events)
+{
+ int count;
+ struct cfl_list *head;
+ struct ctrace_span_event *event;
+
+ count = cfl_list_size(events);
+ mpack_start_array(writer, count);
+
+ cfl_list_foreach(head, events) {
+ event = cfl_list_entry(head, struct ctrace_span_event, _head);
+
+ /* start event map */
+ mpack_start_map(writer, 4);
+
+ /* time_unix_nano */
+ mpack_write_cstr(writer, "time_unix_nano");
+ mpack_write_u64(writer, event->time_unix_nano);
+
+ /* name */
+ mpack_write_cstr(writer, "name");
+ if (event->name) {
+ mpack_write_str(writer, event->name, cfl_sds_len(event->name));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* attributes */
+ mpack_write_cstr(writer, "attributes");
+ if (event->attr) {
+ pack_attributes(writer, event->attr);
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* dropped_attributes_count */
+ mpack_write_cstr(writer, "dropped_attributes_count");
+ mpack_write_u32(writer, event->dropped_attr_count);
+
+ /* finish event map */
+ mpack_finish_map(writer);
+ }
+
+ mpack_finish_array(writer);
+}
+
+static void pack_links(mpack_writer_t *writer, struct cfl_list *links)
+{
+ int count;
+ struct cfl_list *head;
+ struct ctrace_link *link;
+
+ count = cfl_list_size(links);
+ mpack_start_array(writer, count);
+
+ cfl_list_foreach(head, links) {
+ link = cfl_list_entry(head, struct ctrace_link, _head);
+
+ /* start map */
+ mpack_start_map(writer, 5);
+
+ /* trace_id */
+ mpack_write_cstr(writer, "trace_id");
+ pack_id(writer, link->trace_id);
+
+ /* span_id */
+ mpack_write_cstr(writer, "span_id");
+ pack_id(writer, link->span_id);
+
+ /* trace_state */
+ mpack_write_cstr(writer, "trace_state");
+ if (link->trace_state) {
+ mpack_write_str(writer, link->trace_state, cfl_sds_len(link->trace_state));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* attributes */
+ mpack_write_cstr(writer, "attributes");
+ if (link->attr) {
+ pack_attributes(writer, link->attr);
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* dropped_attributes_count */
+ mpack_write_cstr(writer, "dropped_attributes_count");
+ mpack_write_u32(writer, link->dropped_attr_count);
+
+ /* end map */
+ mpack_finish_map(writer);
+ }
+
+ mpack_finish_array(writer);
+}
+
+static void pack_span(mpack_writer_t *writer, struct ctrace_span *span)
+{
+ mpack_start_map(writer, 13);
+
+ /* trace_id */
+ mpack_write_cstr(writer, "trace_id");
+ pack_id(writer, span->trace_id);
+
+ /* span_id */
+ mpack_write_cstr(writer, "span_id");
+ pack_id(writer, span->span_id);
+
+ /* parent_span_id */
+ mpack_write_cstr(writer, "parent_span_id");
+ pack_id(writer, span->parent_span_id);
+
+ /* trace_state */
+ mpack_write_cstr(writer, "trace_state");
+ if (span->trace_state) {
+ mpack_write_str(writer, span->trace_state, cfl_sds_len(span->trace_state));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* name */
+ mpack_write_cstr(writer, "name");
+ if (span->name) {
+ mpack_write_str(writer, span->name, cfl_sds_len(span->name));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* kind */
+ mpack_write_cstr(writer, "kind");
+ mpack_write_u32(writer, span->kind);
+
+ /* start_time_unix_nano */
+ mpack_write_cstr(writer, "start_time_unix_nano");
+ mpack_write_u64(writer, span->start_time_unix_nano);
+
+ /* end_time_unix_nano */
+ mpack_write_cstr(writer, "end_time_unix_nano");
+ mpack_write_u64(writer, span->end_time_unix_nano);
+
+ /* attributes */
+ mpack_write_cstr(writer, "attributes");
+ if (span->attr) {
+ pack_attributes(writer, span->attr);
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ /* dropped_attributes_count */
+ mpack_write_cstr(writer, "dropped_attributes_count");
+ mpack_write_u32(writer, span->dropped_attr_count);
+
+ /* events */
+ mpack_write_cstr(writer, "events");
+ pack_events(writer, &span->events);
+
+ /* links */
+ mpack_write_cstr(writer, "links");
+ pack_links(writer, &span->links);
+
+ /* span_status */
+ mpack_write_cstr(writer, "status");
+ mpack_start_map(writer, 2);
+ mpack_write_cstr(writer, "code");
+ mpack_write_i32(writer, span->status.code);
+ mpack_write_cstr(writer, "message");
+ if (span->status.message) {
+ mpack_write_str(writer, span->status.message, cfl_sds_len(span->status.message));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+ mpack_finish_map(writer);
+
+ mpack_finish_map(writer);
+}
+
+static void pack_spans(mpack_writer_t *writer, struct cfl_list *spans)
+{
+ int count;
+ struct cfl_list *head;
+ struct ctrace_span *span;
+
+ count = cfl_list_size(spans);
+ mpack_start_array(writer, count);
+
+ cfl_list_foreach(head, spans) {
+ span = cfl_list_entry(head, struct ctrace_span, _head);
+ pack_span(writer, span);
+ }
+
+ mpack_finish_array(writer);
+}
+
+static void pack_scope_spans(mpack_writer_t *writer, struct cfl_list *scope_spans)
+{
+ int count;
+ struct cfl_list *head;
+ struct ctrace_scope_span *scope_span;
+
+ count = cfl_list_size(scope_spans);
+
+ mpack_write_cstr(writer, "scope_spans");
+ mpack_start_array(writer, count);
+
+ cfl_list_foreach(head, scope_spans) {
+ scope_span = cfl_list_entry(head, struct ctrace_scope_span, _head);
+
+ mpack_start_map(writer, 3);
+
+ /* scope */
+ mpack_write_cstr(writer, "scope");
+ pack_instrumentation_scope(writer, scope_span->instrumentation_scope);
+
+ /* spans */
+ mpack_write_cstr(writer, "spans");
+ pack_spans(writer, &scope_span->spans);
+
+ /* schema_url */
+ mpack_write_cstr(writer, "schema_url");
+ if (scope_span->schema_url) {
+ mpack_write_str(writer, scope_span->schema_url, cfl_sds_len(scope_span->schema_url));
+ }
+ else {
+ mpack_write_nil(writer);
+ }
+
+ mpack_finish_map(writer);
+ }
+
+ mpack_finish_array(writer);
+}
+
+int ctr_encode_msgpack_create(struct ctrace *ctx, char **out_buf, size_t *out_size)
+{
+ int count;
+ char *data;
+ size_t size;
+ mpack_writer_t writer;
+ struct cfl_list *head;
+ struct ctrace_resource_span *resource_span;
+ struct ctrace_resource *resource;
+
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ mpack_writer_init_growable(&writer, &data, &size);
+
+ /* root map */
+ mpack_start_map(&writer, 1);
+
+ /* resourceSpan */
+ mpack_write_cstr(&writer, "resourceSpans");
+
+ /* array */
+ count = cfl_list_size(&ctx->resource_spans);
+ mpack_start_array(&writer, count);
+
+ cfl_list_foreach(head, &ctx->resource_spans) {
+ resource_span = cfl_list_entry(head, struct ctrace_resource_span, _head);
+
+ /* resourceSpans is an array of maps, each maps containers a 'resource', 'schema_url' and 'scopeSpans' entry */
+ mpack_start_map(&writer, 3);
+
+ /* resource key */
+ resource = resource_span->resource;
+ mpack_write_cstr(&writer, "resource");
+
+ /* resource val */
+ mpack_start_map(&writer, 2);
+
+ /* resource[0]: attributes */
+ mpack_write_cstr(&writer, "attributes");
+ if (resource->attr) {
+ pack_attributes(&writer, resource->attr);
+ }
+ else {
+ mpack_write_nil(&writer);
+ }
+
+ /* resource[1]: dropped_attributes_count */
+ mpack_write_cstr(&writer, "dropped_attributes_count");
+ mpack_write_u32(&writer, resource->dropped_attr_count);
+
+ mpack_finish_map(&writer);
+
+ /* schema_url */
+ mpack_write_cstr(&writer, "schema_url");
+ if (resource_span->schema_url) {
+ mpack_write_str(&writer, resource_span->schema_url, cfl_sds_len(resource_span->schema_url));
+ }
+ else {
+ mpack_write_nil(&writer);
+ }
+
+ /* scopeSpans */
+ pack_scope_spans(&writer, &resource_span->scope_spans);
+
+ mpack_finish_map(&writer); /* !resourceSpans map value */
+ }
+
+ mpack_finish_array(&writer);
+ mpack_finish_map(&writer);
+
+ if (mpack_writer_destroy(&writer) != mpack_ok) {
+ fprintf(stderr, "An error occurred encoding the data!\n");
+ return -1;
+ }
+
+ *out_buf = data;
+ *out_size = size;
+
+ return 0;
+}
+
+void ctr_encode_msgpack_destroy(char *buf)
+{
+ free(buf);
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_encode_opentelemetry.c b/fluent-bit/lib/ctraces/src/ctr_encode_opentelemetry.c
new file mode 100644
index 000000000..e8a95f149
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_encode_opentelemetry.c
@@ -0,0 +1,1322 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+#include <fluent-otel-proto/fluent-otel.h>
+
+static inline Opentelemetry__Proto__Common__V1__AnyValue *ctr_variant_to_otlp_any_value(struct cfl_variant *value);
+static inline Opentelemetry__Proto__Common__V1__KeyValue *ctr_variant_kvpair_to_otlp_kvpair(struct cfl_kvpair *input_pair);
+static inline Opentelemetry__Proto__Common__V1__AnyValue *ctr_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);
+ value->string_value = NULL;
+ }
+ }
+ 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);
+ value = NULL;
+ }
+}
+
+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 *));
+
+ if (result == NULL) {
+ ctr_errno();
+ return NULL;
+ }
+
+ 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 *ctr_variant_kvpair_to_otlp_kvpair(struct cfl_kvpair *input_pair)
+{
+ Opentelemetry__Proto__Common__V1__KeyValue *kv;
+
+ kv = otlp_kvpair_value_initialize();
+ if (kv == NULL) {
+ ctr_errno();
+ return NULL;
+ }
+
+ kv->key = strdup(input_pair->key);
+ if (kv->key == NULL) {
+ ctr_errno();
+ free(kv);
+ return NULL;
+ }
+
+ kv->value = ctr_variant_to_otlp_any_value(input_pair->val);
+ if (kv->value == NULL) {
+ ctr_errno();
+ free(kv->key);
+ free(kv);
+ return NULL;
+ }
+
+ return kv;
+}
+
+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);
+ pair_list = NULL;
+ }
+}
+
+static inline Opentelemetry__Proto__Common__V1__KeyValue **ctr_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);
+
+ if (result != NULL) {
+ index = 0;
+
+ cfl_list_foreach(iterator, &kvlist->list) {
+ kvpair = cfl_list_entry(iterator, struct cfl_kvpair, _head);
+
+ keyvalue = ctr_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 *ctr_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 = ctr_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 *ctr_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 = ctr_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 *ctr_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 *ctr_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 *ctr_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 *ctr_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 *ctr_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 *ctr_variant_to_otlp_any_value(struct cfl_variant *value)
+{
+ Opentelemetry__Proto__Common__V1__AnyValue *result;
+
+ if (value->type == CFL_VARIANT_STRING) {
+ result = ctr_variant_string_to_otlp_any_value(value);
+ }
+ else if (value->type == CFL_VARIANT_BOOL) {
+ result = ctr_variant_boolean_to_otlp_any_value(value);
+ }
+ else if (value->type == CFL_VARIANT_INT) {
+ result = ctr_variant_int64_to_otlp_any_value(value);
+ }
+ else if (value->type == CFL_VARIANT_DOUBLE) {
+ result = ctr_variant_double_to_otlp_any_value(value);
+ }
+ else if (value->type == CFL_VARIANT_ARRAY) {
+ result = ctr_variant_array_to_otlp_any_value(value);
+ }
+ else if (value->type == CFL_VARIANT_KVLIST) {
+ result = ctr_variant_kvlist_to_otlp_any_value(value);
+ }
+ else if (value->type == CFL_VARIANT_BYTES) {
+ result = ctr_variant_binary_to_otlp_any_value(value);
+ }
+ else if (value->type == CFL_VARIANT_REFERENCE) {
+ result = ctr_variant_string_to_otlp_any_value(value);
+ }
+ else {
+ result = NULL;
+ }
+
+ return result;
+}
+
+static Opentelemetry__Proto__Common__V1__KeyValue **set_attributes_from_ctr(struct ctrace_attributes *attr)
+{
+ if(attr == NULL) {
+ return NULL;
+ }
+
+ return ctr_kvlist_to_otlp_kvpair_list(attr->kv);
+}
+
+static Opentelemetry__Proto__Resource__V1__Resource *initialize_resource()
+{
+ Opentelemetry__Proto__Resource__V1__Resource *resource;
+
+ resource = calloc(1, sizeof(Opentelemetry__Proto__Resource__V1__Resource));
+
+ if (!resource) {
+ ctr_errno();
+ return NULL;
+ }
+
+ opentelemetry__proto__resource__v1__resource__init(resource);
+
+ return resource;
+}
+
+static size_t get_attributes_count(struct ctrace_attributes *attr)
+{
+ if (attr == NULL) {
+ return 0;
+ }
+
+ return cfl_kvlist_count(attr->kv);
+}
+
+static Opentelemetry__Proto__Resource__V1__Resource *ctr_set_resource(struct ctrace_resource *resource)
+{
+ Opentelemetry__Proto__Resource__V1__Resource *otel_resource;
+
+ otel_resource = initialize_resource();
+ if (!otel_resource) {
+ return NULL;
+ }
+
+ otel_resource->n_attributes = get_attributes_count(resource->attr);
+ otel_resource->attributes = set_attributes_from_ctr(resource->attr);
+ otel_resource->dropped_attributes_count = resource->dropped_attr_count;
+
+ return otel_resource;
+}
+
+static void otel_span_set_trace_id(Opentelemetry__Proto__Trace__V1__Span *span,
+ struct ctrace_id *trace_id)
+{
+ size_t len;
+ uint8_t *trace_id_str;
+
+ if (!trace_id) {
+ return;
+ }
+
+ len = ctr_id_get_len(trace_id);
+ trace_id_str = ctr_id_get_buf(trace_id);
+
+ span->trace_id.len = len;
+ span->trace_id.data = trace_id_str;
+}
+
+static void otel_span_set_span_id(Opentelemetry__Proto__Trace__V1__Span *span,
+ struct ctrace_id *span_id)
+{
+ size_t len;
+ uint8_t *span_id_str;
+
+ if (!span_id) {
+ return;
+ }
+
+ len = ctr_id_get_len(span_id);
+ span_id_str = ctr_id_get_buf(span_id);
+
+ span->span_id.len = len;
+ span->span_id.data = span_id_str;
+}
+
+static void otel_span_set_parent_span_id(Opentelemetry__Proto__Trace__V1__Span *span,
+ struct ctrace_id *parent)
+{
+ size_t len;
+ uint8_t *parent_id_str;
+
+ if (!parent) {
+ return;
+ }
+
+ len = ctr_id_get_len(parent);
+ parent_id_str = ctr_id_get_buf(parent);
+
+ span->parent_span_id.len = len;
+ span->parent_span_id.data = parent_id_str;
+}
+
+static void otel_span_set_kind(Opentelemetry__Proto__Trace__V1__Span *otel_span,
+ int kind)
+{
+ switch (kind) {
+ case CTRACE_SPAN_INTERNAL:
+ otel_span->kind = OPENTELEMETRY__PROTO__TRACE__V1__SPAN__SPAN_KIND__SPAN_KIND_INTERNAL;
+ break;
+ case CTRACE_SPAN_SERVER:
+ otel_span->kind = OPENTELEMETRY__PROTO__TRACE__V1__SPAN__SPAN_KIND__SPAN_KIND_SERVER;
+ break;
+ case CTRACE_SPAN_CLIENT:
+ otel_span->kind = OPENTELEMETRY__PROTO__TRACE__V1__SPAN__SPAN_KIND__SPAN_KIND_CLIENT;
+ break;
+ case CTRACE_SPAN_PRODUCER:
+ otel_span->kind = OPENTELEMETRY__PROTO__TRACE__V1__SPAN__SPAN_KIND__SPAN_KIND_PRODUCER;
+ break;
+ case CTRACE_SPAN_CONSUMER:
+ otel_span->kind = OPENTELEMETRY__PROTO__TRACE__V1__SPAN__SPAN_KIND__SPAN_KIND_CONSUMER;
+ break;
+ default:
+ otel_span->kind = OPENTELEMETRY__PROTO__TRACE__V1__SPAN__SPAN_KIND__SPAN_KIND_UNSPECIFIED;
+ break;
+ }
+}
+
+static void otel_span_set_start_time(Opentelemetry__Proto__Trace__V1__Span *span,
+ uint64_t start_time)
+{
+ span->start_time_unix_nano = start_time;
+}
+
+static void otel_span_set_end_time(Opentelemetry__Proto__Trace__V1__Span *span,
+ uint64_t end_time)
+{
+ span->end_time_unix_nano = end_time;
+}
+
+static void otel_span_set_attributes(Opentelemetry__Proto__Trace__V1__Span *span,
+ struct ctrace_attributes *attr)
+{
+ span->n_attributes = get_attributes_count(attr);
+ span->attributes = set_attributes_from_ctr(attr);
+}
+
+static void otel_span_set_dropped_attributes_count(Opentelemetry__Proto__Trace__V1__Span *span,
+ uint32_t dropped_attr_count)
+{
+ span->dropped_attributes_count = dropped_attr_count;
+}
+
+static Opentelemetry__Proto__Trace__V1__Span__Event *set_event(struct ctrace_span_event *ctr_event)
+{
+ Opentelemetry__Proto__Trace__V1__Span__Event *event;
+
+ event = calloc(1, sizeof(Opentelemetry__Proto__Trace__V1__Span__Event));
+ opentelemetry__proto__trace__v1__span__event__init(event);
+
+ event->time_unix_nano = ctr_event->time_unix_nano;
+ event->name = ctr_event->name;
+ event->n_attributes = ctr_attributes_count(ctr_event->attr);
+ event->attributes = set_attributes_from_ctr(ctr_event->attr);
+ event->dropped_attributes_count = ctr_event->dropped_attr_count;
+
+ return event;
+}
+
+static Opentelemetry__Proto__Trace__V1__Span__Event **set_events_from_ctr(struct cfl_list *events)
+{
+ int count;
+ int event_index;
+ struct cfl_list *head;
+ struct ctrace_span_event *ctr_event;
+
+ count = cfl_list_size(events);
+
+ Opentelemetry__Proto__Trace__V1__Span__Event **event_arr;
+
+ event_arr = calloc(count, sizeof(Opentelemetry__Proto__Trace__V1__Span__Event *));
+
+ event_index = 0;
+ cfl_list_foreach(head, events) {
+ ctr_event = cfl_list_entry(head, struct ctrace_span_event, _head);
+ event_arr[event_index++] = set_event(ctr_event);
+ }
+
+ return event_arr;
+}
+
+static void otel_span_set_events(Opentelemetry__Proto__Trace__V1__Span *otel_span,
+ struct cfl_list *events)
+{
+ otel_span->n_events = cfl_list_size(events);
+ otel_span->events = set_events_from_ctr(events);
+}
+
+static void otel_span_set_dropped_events_count(Opentelemetry__Proto__Trace__V1__Span *span,
+ uint32_t dropped_events_count)
+{
+ span->dropped_events_count = dropped_events_count;
+}
+
+static void otel_span_set_name(Opentelemetry__Proto__Trace__V1__Span *otel_span,
+ char *name)
+{
+ otel_span->name = name;
+}
+
+static void otel_span_set_trace_state(Opentelemetry__Proto__Trace__V1__Span *otel_span,
+ char *trace_state)
+{
+ otel_span->trace_state = trace_state;
+}
+
+static void otel_span_set_status(Opentelemetry__Proto__Trace__V1__Span *otel_span,
+ struct ctrace_span_status status)
+{
+ Opentelemetry__Proto__Trace__V1__Status *otel_status;
+
+ otel_status = calloc(1, sizeof(Opentelemetry__Proto__Trace__V1__Status));
+ opentelemetry__proto__trace__v1__status__init(otel_status);
+
+ otel_status->code = status.code;
+ otel_status->message = status.message;
+
+ otel_span->status = otel_status;
+}
+
+static void otel_span_set_links(Opentelemetry__Proto__Trace__V1__Span *otel_span,
+ struct cfl_list *links)
+{
+ int count;
+ int link_index;
+ struct cfl_list *head;
+ struct ctrace_link *link;
+ size_t link_span_id_size;
+ size_t link_trace_id_size;
+ uint8_t *link_trace_id;
+ uint8_t *link_span_id;
+
+ count = cfl_list_size(links);
+
+ Opentelemetry__Proto__Trace__V1__Span__Link **otel_links;
+ Opentelemetry__Proto__Trace__V1__Span__Link *otel_link;
+
+ otel_links = calloc(count, sizeof(Opentelemetry__Proto__Trace__V1__Span__Link *));
+
+ link_index = 0;
+
+ cfl_list_foreach(head, links) {
+ link = cfl_list_entry(head, struct ctrace_link, _head);
+
+ otel_link = calloc(1, sizeof(Opentelemetry__Proto__Trace__V1__Span__Link));
+ opentelemetry__proto__trace__v1__span__link__init(otel_link);
+
+ if (link->trace_id) {
+ link_trace_id_size = ctr_id_get_len(link->trace_id);
+ link_trace_id = ctr_id_get_buf(link->trace_id);
+
+ otel_link->trace_id.len = link_trace_id_size;
+ otel_link->trace_id.data = link_trace_id;
+ }
+
+ if (link->span_id) {
+ link_span_id_size = ctr_id_get_len(link->span_id);
+ link_span_id = ctr_id_get_buf(link->span_id);
+
+ otel_link->span_id.len = link_span_id_size;
+ otel_link->span_id.data = link_span_id;
+ }
+
+ otel_link->trace_state = link->trace_state;
+
+ otel_link->n_attributes = get_attributes_count(link->attr);
+ otel_link->attributes = set_attributes_from_ctr(link->attr);
+ otel_link->dropped_attributes_count = link->dropped_attr_count;
+
+ otel_links[link_index++] = otel_link;
+ }
+
+ otel_span->n_links = count;
+ otel_span->links = otel_links;
+}
+
+static void set_span(Opentelemetry__Proto__Trace__V1__Span *otel_span,
+ struct ctrace_span *span)
+{
+ otel_span_set_name(otel_span, span->name);
+ otel_span_set_trace_id(otel_span, span->trace_id);
+ otel_span_set_span_id(otel_span, span->span_id);
+ otel_span_set_parent_span_id(otel_span, span->parent_span_id);
+ otel_span_set_kind(otel_span, span->kind);
+ otel_span_set_trace_state(otel_span, span->trace_state);
+ otel_span_set_start_time(otel_span, span->start_time_unix_nano);
+ otel_span_set_end_time(otel_span, span->end_time_unix_nano);
+ otel_span_set_status(otel_span, span->status);
+
+ otel_span_set_attributes(otel_span, span->attr);
+ otel_span_set_dropped_attributes_count(otel_span, span->dropped_attr_count);
+ otel_span_set_events(otel_span, &span->events);
+ otel_span_set_dropped_events_count(otel_span, span->dropped_events_count);
+ otel_span_set_links(otel_span, &span->links);
+}
+
+static Opentelemetry__Proto__Trace__V1__Span **initialize_spans(size_t span_count)
+{
+ Opentelemetry__Proto__Trace__V1__Span **spans;
+
+ spans = calloc(span_count, sizeof(Opentelemetry__Proto__Trace__V1__Span *));
+ if (!spans) {
+ ctr_errno();
+ return NULL;
+ }
+
+ return spans;
+}
+
+static Opentelemetry__Proto__Trace__V1__Span *initialize_span()
+{
+ Opentelemetry__Proto__Trace__V1__Span *span;
+
+ span = calloc(1, sizeof(Opentelemetry__Proto__Trace__V1__Span));
+ if (!span) {
+ ctr_errno();
+ return NULL;
+ }
+
+ opentelemetry__proto__trace__v1__span__init(span);
+
+ return span;
+}
+
+static Opentelemetry__Proto__Trace__V1__Span **set_spans(struct ctrace_scope_span *scope_span)
+{
+ int span_count;
+ int span_index;
+ struct cfl_list *head;
+ struct ctrace_span *span;
+
+ Opentelemetry__Proto__Trace__V1__Span **spans;
+ Opentelemetry__Proto__Trace__V1__Span *otel_span;
+
+ span_count = cfl_list_size(&scope_span->spans);
+ spans = initialize_spans(span_count);
+ if (!spans) {
+ return NULL;
+ }
+
+ span_index = 0;
+
+ cfl_list_foreach(head, &scope_span->spans) {
+ span = cfl_list_entry(head, struct ctrace_span, _head);
+
+ otel_span = initialize_span();
+ if (!otel_span) {
+ return NULL;
+ }
+
+ set_span(otel_span, span);
+ spans[span_index++] = otel_span;
+ }
+
+ return spans;
+}
+
+static Opentelemetry__Proto__Common__V1__InstrumentationScope *initialize_instrumentation_scope()
+{
+ Opentelemetry__Proto__Common__V1__InstrumentationScope *instrumentation_scope;
+
+ instrumentation_scope = calloc(1, sizeof(Opentelemetry__Proto__Common__V1__InstrumentationScope));
+ if (!instrumentation_scope) {
+ ctr_errno();
+ return NULL;
+ }
+ opentelemetry__proto__common__v1__instrumentation_scope__init(instrumentation_scope);
+
+ return instrumentation_scope;
+}
+
+static Opentelemetry__Proto__Common__V1__InstrumentationScope *set_instrumentation_scope(struct ctrace_instrumentation_scope *instrumentation_scope)
+{
+ Opentelemetry__Proto__Common__V1__InstrumentationScope *otel_scope;
+
+ otel_scope = initialize_instrumentation_scope();
+ if (!otel_scope) {
+ return NULL;
+ }
+
+ otel_scope->name = instrumentation_scope->name;
+ otel_scope->version = instrumentation_scope->version;
+ otel_scope->n_attributes = get_attributes_count(instrumentation_scope->attr);
+ otel_scope->dropped_attributes_count = instrumentation_scope->dropped_attr_count;
+ otel_scope->attributes = set_attributes_from_ctr(instrumentation_scope->attr);;
+
+ return otel_scope;
+}
+
+static Opentelemetry__Proto__Trace__V1__ScopeSpans **initialize_scope_spans(size_t count)
+{
+ Opentelemetry__Proto__Trace__V1__ScopeSpans **scope_spans;
+
+ scope_spans = calloc(count, sizeof(Opentelemetry__Proto__Trace__V1__ScopeSpans *));
+ if (!scope_spans) {
+ ctr_errno();
+ return NULL;
+ }
+
+ return scope_spans;
+}
+
+static Opentelemetry__Proto__Trace__V1__ScopeSpans *initialize_scope_span()
+{
+ Opentelemetry__Proto__Trace__V1__ScopeSpans *scope_span;
+
+ scope_span = calloc(1, sizeof(Opentelemetry__Proto__Trace__V1__ScopeSpans));
+ if (!scope_span) {
+ ctr_errno();
+ return NULL;
+ }
+
+ opentelemetry__proto__trace__v1__scope_spans__init(scope_span);
+
+ return scope_span;
+}
+
+static Opentelemetry__Proto__Trace__V1__ScopeSpans **set_scope_spans(struct ctrace_resource_span *resource_span)
+{
+ int span_count;
+ int scope_span_count;
+ int scope_span_index;
+ struct cfl_list *head;
+ struct ctrace_scope_span *scope_span;
+
+ Opentelemetry__Proto__Trace__V1__ScopeSpans **scope_spans;
+ Opentelemetry__Proto__Trace__V1__ScopeSpans *otel_scope_span;
+
+
+ scope_span_count = cfl_list_size(&resource_span->scope_spans);
+ scope_spans = initialize_scope_spans(scope_span_count);
+ if (!scope_spans) {
+ return NULL;
+ }
+
+ scope_span_index = 0;
+
+ cfl_list_foreach(head, &resource_span->scope_spans) {
+ scope_span = cfl_list_entry(head, struct ctrace_scope_span, _head);
+
+ otel_scope_span = initialize_scope_span();
+ if (!otel_scope_span) {
+ return NULL;
+ }
+
+ otel_scope_span->schema_url = scope_span->schema_url;
+ otel_scope_span->scope = set_instrumentation_scope(scope_span->instrumentation_scope);
+
+ span_count = cfl_list_size(&scope_span->spans);
+ otel_scope_span->n_spans = span_count;
+ otel_scope_span->spans = set_spans(scope_span);
+
+ scope_spans[scope_span_index++] = otel_scope_span;
+ }
+
+ return scope_spans;
+}
+
+static Opentelemetry__Proto__Trace__V1__ResourceSpans **initialize_resource_spans(size_t count)
+{
+ Opentelemetry__Proto__Trace__V1__ResourceSpans **resource_spans;
+
+ resource_spans = calloc(count, sizeof(Opentelemetry__Proto__Trace__V1__ResourceSpans *));
+ if (!resource_spans) {
+ ctr_errno();
+ return NULL;
+ }
+
+ return resource_spans;
+}
+
+static Opentelemetry__Proto__Trace__V1__ResourceSpans *initialize_resource_span()
+{
+ Opentelemetry__Proto__Trace__V1__ResourceSpans *resource_span;
+
+ resource_span = calloc(1, sizeof(Opentelemetry__Proto__Trace__V1__ResourceSpans));
+ if (!resource_span) {
+ ctr_errno();
+ return NULL;
+ }
+
+ opentelemetry__proto__trace__v1__resource_spans__init(resource_span);
+
+ return resource_span;
+}
+
+
+static Opentelemetry__Proto__Trace__V1__ResourceSpans **set_resource_spans(struct ctrace *ctr)
+{
+ struct ctrace_resource_span *resource_span;
+ struct cfl_list *head;
+ int resource_span_count;
+ int resource_span_index;
+
+ Opentelemetry__Proto__Trace__V1__ResourceSpans **rs;
+ Opentelemetry__Proto__Trace__V1__ResourceSpans *otel_resource_span;
+ Opentelemetry__Proto__Trace__V1__ScopeSpans **scope_spans;
+
+ resource_span_count = cfl_list_size(&ctr->resource_spans);
+ rs = initialize_resource_spans(resource_span_count);
+
+ resource_span_index = 0;
+
+ cfl_list_foreach(head, &ctr->resource_spans) {
+ resource_span = cfl_list_entry(head, struct ctrace_resource_span, _head);
+
+ otel_resource_span = initialize_resource_span();
+ if (!otel_resource_span) {
+ return NULL;
+ }
+ otel_resource_span->resource = ctr_set_resource(resource_span->resource);
+
+ otel_resource_span->n_scope_spans = cfl_list_size(&resource_span->scope_spans);
+ scope_spans = set_scope_spans(resource_span);
+ otel_resource_span->scope_spans = scope_spans;
+
+ otel_resource_span->schema_url = resource_span->schema_url;
+ rs[resource_span_index++] = otel_resource_span;
+ }
+
+ return rs;
+
+}
+
+static Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest *initialize_export_service_request()
+{
+ Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest *req;
+
+ req = malloc(sizeof(Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest));
+ if (!req) {
+ ctr_errno();
+ return NULL;
+ }
+ opentelemetry__proto__collector__trace__v1__export_trace_service_request__init(req);
+
+ return req;
+}
+
+static Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest *create_export_service_request(struct ctrace *ctr)
+{
+ Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest *req;
+ Opentelemetry__Proto__Trace__V1__ResourceSpans **rs;
+
+ req = initialize_export_service_request();
+ if (!req) {
+ return NULL;
+ }
+
+ req->n_resource_spans = cfl_list_size(&ctr->resource_spans);
+ rs = set_resource_spans(ctr);
+ req->resource_spans = rs;
+
+ return req;
+}
+
+static void destroy_attributes(Opentelemetry__Proto__Common__V1__KeyValue **attributes, size_t count)
+{
+ otlp_kvpair_list_destroy(attributes, count);
+}
+
+static void destroy_resource(Opentelemetry__Proto__Resource__V1__Resource *resource)
+{
+ destroy_attributes(resource->attributes, resource->n_attributes);
+
+ resource->attributes = NULL;
+ resource->n_attributes = 0;
+ resource->dropped_attributes_count = 0;
+
+ free(resource);
+}
+
+static void destroy_id(ProtobufCBinaryData id){
+ id.len = 0;
+
+ if (id.data) {
+ id.data = NULL;
+ }
+}
+
+static void destroy_event(Opentelemetry__Proto__Trace__V1__Span__Event *event)
+{
+ destroy_attributes(event->attributes, event->n_attributes);
+
+ event->time_unix_nano = 0;
+ event->name = NULL;
+ event->attributes = NULL;
+ event->n_attributes = 0;
+ event->dropped_attributes_count = 0;
+
+ free(event);
+}
+
+static void destroy_events(Opentelemetry__Proto__Trace__V1__Span__Event **events, size_t count)
+{
+ int event_index;
+ Opentelemetry__Proto__Trace__V1__Span__Event *event;
+
+ for (event_index = 0; event_index < count; event_index++) {
+ event = events[event_index];
+ destroy_event(event);
+ }
+
+ free(events);
+}
+
+static void destroy_link(Opentelemetry__Proto__Trace__V1__Span__Link *link)
+{
+ destroy_attributes(link->attributes, link->n_attributes);
+
+ destroy_id(link->trace_id);
+ destroy_id(link->span_id);
+
+ link->trace_state = NULL;
+ link->attributes = NULL;
+ link->n_attributes = 0;
+ link->dropped_attributes_count = 0;
+
+ free(link);
+}
+
+
+static void destroy_links(Opentelemetry__Proto__Trace__V1__Span__Link **links, size_t count)
+{
+ int link_index;
+ Opentelemetry__Proto__Trace__V1__Span__Link *link;
+
+ for (link_index = 0; link_index < count; link_index++) {
+ link = links[link_index];
+ destroy_link(link);
+ }
+
+ free(links);
+}
+
+static void destroy_span(Opentelemetry__Proto__Trace__V1__Span *span)
+{
+ destroy_events(span->events, span->n_events);
+ destroy_attributes(span->attributes, span->n_attributes);
+ destroy_links(span->links, span->n_links);
+
+ span->attributes = NULL;
+ span->n_attributes = 0;
+ span->dropped_attributes_count = 0;
+
+ span->events = NULL;
+ span->n_events = 0;
+ span->dropped_events_count = 0;
+
+ span->links = NULL;
+ span->n_links = 0;
+ span->dropped_links_count = 0;
+
+ span->start_time_unix_nano = 0;
+ span->end_time_unix_nano = 0;
+
+ destroy_id(span->trace_id);
+ destroy_id(span->span_id);
+ destroy_id(span->parent_span_id);
+ span->trace_state = NULL;
+
+ span->name = NULL;
+ span->kind = 0;
+
+ span->status->message = NULL;
+ span->status->code = 0;
+ free(span->status);
+
+ free(span);
+}
+
+static void destroy_spans(Opentelemetry__Proto__Trace__V1__Span **spans, size_t count)
+{
+ int span_index;
+
+ for (span_index = 0; span_index < count; span_index++) {
+ destroy_span(spans[span_index]);
+ }
+
+ free(spans);
+}
+
+static void destroy_scope(Opentelemetry__Proto__Common__V1__InstrumentationScope *scope)
+{
+ if (scope->name) {
+ scope->name = NULL;
+ }
+
+ scope->version = NULL;
+
+ destroy_attributes(scope->attributes, scope->n_attributes);
+ scope->attributes = NULL;
+ scope->n_attributes = 0;
+ scope->dropped_attributes_count = 0;
+
+ free(scope);
+}
+
+static void destroy_scope_span(Opentelemetry__Proto__Trace__V1__ScopeSpans *scope_span)
+{
+ if (scope_span->schema_url) {
+ scope_span->schema_url = NULL;
+ }
+
+ if (scope_span->scope) {
+ destroy_scope(scope_span->scope);
+ }
+
+ destroy_spans(scope_span->spans, scope_span->n_spans);
+ scope_span->spans = NULL;
+ scope_span->n_spans = 0;
+
+ free(scope_span);
+}
+
+static void destroy_scope_spans(Opentelemetry__Proto__Trace__V1__ScopeSpans **scope_spans,
+ size_t count)
+{
+ int scope_span_index;
+ Opentelemetry__Proto__Trace__V1__ScopeSpans *scope_span;
+
+ for (scope_span_index = 0; scope_span_index < count; scope_span_index++) {
+ scope_span = scope_spans[scope_span_index];
+ destroy_scope_span(scope_span);
+ }
+
+ free(scope_spans);
+}
+
+static void destroy_resource_spans(Opentelemetry__Proto__Trace__V1__ResourceSpans **rs,
+ int resource_span_count)
+{
+ Opentelemetry__Proto__Trace__V1__ResourceSpans *resource_span;
+ int resource_span_index;
+
+ for(resource_span_index = 0; resource_span_index < resource_span_count; resource_span_index++) {
+ resource_span = rs[resource_span_index];
+
+ destroy_resource(resource_span->resource);
+ resource_span->resource = NULL;
+
+ destroy_scope_spans(resource_span->scope_spans, resource_span->n_scope_spans);
+ resource_span->scope_spans = NULL;
+ resource_span->n_scope_spans = 0;
+ resource_span->schema_url = NULL;
+
+ free(resource_span);
+ }
+ free(rs);
+}
+
+static void destroy_export_service_request(Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest *req)
+{
+ destroy_resource_spans(req->resource_spans, req->n_resource_spans);
+ req->n_resource_spans = 0;
+ req->resource_spans = NULL;
+
+ free(req);
+ req = NULL;
+}
+
+cfl_sds_t ctr_encode_opentelemetry_create(struct ctrace *ctr)
+{
+ cfl_sds_t buf;
+ size_t len;
+ Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceRequest *req;
+
+ req = create_export_service_request(ctr);
+
+ len = opentelemetry__proto__collector__trace__v1__export_trace_service_request__get_packed_size(req);
+ buf = cfl_sds_create_size(len);
+ if (!buf) {
+ return NULL;
+ }
+ cfl_sds_set_len(buf, len);
+
+ opentelemetry__proto__collector__trace__v1__export_trace_service_request__pack(req, (uint8_t *)buf);
+
+ destroy_export_service_request(req);
+
+ return buf;
+}
+
+void ctr_encode_opentelemetry_destroy(cfl_sds_t text)
+{
+ cfl_sds_destroy(text);
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_encode_text.c b/fluent-bit/lib/ctraces/src/ctr_encode_text.c
new file mode 100644
index 000000000..aebfd9d76
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_encode_text.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+static inline void sds_cat_safe(cfl_sds_t *buf, char *str)
+{
+ int len;
+
+ len = strlen(str);
+ cfl_sds_cat_safe(buf, str, len);
+}
+
+static void format_string(cfl_sds_t *buf, cfl_sds_t val, int level)
+{
+ char tmp[1024];
+
+ snprintf(tmp, sizeof(tmp) - 1, "'%s'", val);
+ sds_cat_safe(buf, tmp);
+}
+
+static void format_int64(cfl_sds_t *buf, int64_t val, int level)
+{
+ char tmp[1024];
+
+ snprintf(tmp, sizeof(tmp) - 1, "%" PRIi64, val);
+ sds_cat_safe(buf, tmp);
+}
+
+static void format_double(cfl_sds_t *buf, double val, int level)
+{
+ char tmp[1024];
+
+ snprintf(tmp, sizeof(tmp) - 1, "%.17g", val);
+ sds_cat_safe(buf, tmp);
+}
+
+static void format_bool(cfl_sds_t *buf, int val, int level)
+{
+ if (val) {
+ sds_cat_safe(buf, "true");
+ }
+ else {
+ sds_cat_safe(buf, "false");
+ }
+}
+
+static void format_array(cfl_sds_t *buf, struct cfl_array *array, int level)
+{
+ int i;
+ int off = level + 4;
+ char tmp[128];
+ struct cfl_variant *v;
+
+ sds_cat_safe(buf, "[\n");
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s", off, "");
+
+ for (i = 0; i < array->entry_count; i++) {
+ v = array->entries[i];
+
+ sds_cat_safe(buf, tmp);
+
+ if (v->type == CFL_VARIANT_STRING) {
+ format_string(buf, v->data.as_string, off);
+ }
+ else if (v->type == CFL_VARIANT_BOOL) {
+ format_bool(buf, v->data.as_bool, off);
+ }
+ else if (v->type == CFL_VARIANT_INT) {
+ format_int64(buf, v->data.as_int64, off);
+ }
+ else if (v->type == CFL_VARIANT_DOUBLE) {
+ format_double(buf, v->data.as_double, off);
+ }
+ else if (v->type == CFL_VARIANT_ARRAY) {
+ format_array(buf, v->data.as_array, off);
+ }
+
+ if (i + 1 < array->entry_count) {
+ sds_cat_safe(buf, ",\n");
+ }
+ }
+
+ off = level;
+ snprintf(tmp, sizeof(tmp) - 1, "\n%*s]", off, "");
+ sds_cat_safe(buf, tmp);
+}
+
+static void format_attributes(cfl_sds_t *buf, struct cfl_kvlist *kv, int level)
+{
+ int off = level + 4;
+ char tmp[1024];
+ struct cfl_list *head;
+ struct cfl_kvpair *p;
+ struct cfl_variant *v;
+
+ sds_cat_safe(buf, "\n");
+
+ cfl_list_foreach(head, &kv->list) {
+ p = cfl_list_entry(head, struct cfl_kvpair, _head);
+
+ /* key */
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- %s: ", off, "", p->key);
+ sds_cat_safe(buf, tmp);
+
+ /* value */
+ v = p->val;
+ if (v->type == CFL_VARIANT_STRING) {
+ format_string(buf, v->data.as_string, off);
+ }
+ else if (v->type == CFL_VARIANT_BOOL) {
+ format_bool(buf, v->data.as_bool, off);
+ }
+ else if (v->type == CFL_VARIANT_INT) {
+ format_int64(buf, v->data.as_int64, off);
+ }
+ else if (v->type == CFL_VARIANT_DOUBLE) {
+ format_double(buf, v->data.as_double, off);
+ }
+ else if (v->type == CFL_VARIANT_ARRAY) {
+ format_array(buf, v->data.as_array, off);
+ }
+ else if (v->type == CFL_VARIANT_KVLIST) {
+ format_attributes(buf, v->data.as_kvlist, off);
+ }
+
+ sds_cat_safe(buf, "\n");
+ }
+}
+
+static void format_event(cfl_sds_t *buf, struct ctrace_span_event *event, int level)
+{
+ int off = level + 4;
+ char tmp[1024];
+
+ sds_cat_safe(buf, "\n");
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- name: %s\n", off, "", event->name);
+ sds_cat_safe(buf, tmp);
+ off += 4;
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- timestamp : %" PRIu64 "\n", off, "", event->time_unix_nano);
+ sds_cat_safe(buf, tmp);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- dropped_attributes_count: %" PRIu32 "\n", off, "", event->dropped_attr_count);
+ sds_cat_safe(buf, tmp);
+
+ if (ctr_attributes_count(event->attr) > 0) {
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- attributes:", off, "");
+ sds_cat_safe(buf, tmp);
+
+ format_attributes(buf, event->attr->kv, off);
+ }
+ else {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- attributes: none\n", off, "");
+ sds_cat_safe(buf, tmp);
+ }
+
+}
+
+static void format_span(cfl_sds_t *buf, struct ctrace *ctx, struct ctrace_span *span, int level)
+{
+ int min;
+ int off = 1 + (level * 4);
+ char tmp[1024];
+ cfl_sds_t id_hex;
+ struct ctrace_span_event *event;
+ struct ctrace_link *link;
+ struct cfl_list *head;
+
+ min = off + 4;
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s[span '%s']\n", off, "", span->name);
+ sds_cat_safe(buf, tmp);
+
+ /* trace_id */
+ if (span->trace_id) {
+ id_hex = ctr_id_to_lower_base16(span->trace_id);
+ }
+ else {
+ id_hex = cfl_sds_create(CTR_ID_TRACE_DEFAULT);
+ }
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- trace_id : %s\n", min, "", id_hex);
+ sds_cat_safe(buf, tmp);
+ cfl_sds_destroy(id_hex);
+
+ /* span_id */
+ if (span->span_id) {
+ id_hex = ctr_id_to_lower_base16(span->span_id);
+ }
+ else {
+ id_hex = cfl_sds_create(CTR_ID_SPAN_DEFAULT);
+ }
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- span_id : %s\n", min, "", id_hex);
+ sds_cat_safe(buf, tmp);
+ cfl_sds_destroy(id_hex);
+
+ /* parent_span_id */
+ if (span->parent_span_id) {
+ id_hex = ctr_id_to_lower_base16(span->parent_span_id);
+ }
+ else {
+ id_hex = cfl_sds_create("undefined");
+ }
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- parent_span_id : %s\n", min, "", id_hex);
+ sds_cat_safe(buf, tmp);
+ cfl_sds_destroy(id_hex);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- kind : %i (%s)\n", min, "",
+ span->kind, ctr_span_kind_string(span));
+ sds_cat_safe(buf, tmp);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- start_time : %" PRIu64 "\n", min, "",
+ span->start_time_unix_nano);
+ sds_cat_safe(buf, tmp);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- end_time : %" PRIu64 "\n", min, "",
+ span->end_time_unix_nano);
+ sds_cat_safe(buf, tmp);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- dropped_attributes_count: %" PRIu32 "\n", min, "",
+ span->dropped_attr_count);
+ sds_cat_safe(buf, tmp);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- dropped_events_count : %" PRIu32 "\n", min, "",
+ span->dropped_events_count);
+ sds_cat_safe(buf, tmp);
+
+ /* Status */
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- status:\n", min, "");
+ sds_cat_safe(buf, tmp);
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- code : %i\n", min + 4, "", span->status.code);
+ sds_cat_safe(buf, tmp);
+
+ if (span->status.message) {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- message : '%s'\n", min + 4, "", span->status.message);
+ }
+
+ /* span attributes */
+ if (ctr_attributes_count(span->attr) == 0) {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- attributes: none\n", min, "");
+ sds_cat_safe(buf, tmp);
+ }
+ else {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- attributes: ", min, "");
+ sds_cat_safe(buf, tmp);
+ format_attributes(buf, span->attr->kv, min);
+ }
+
+ /* events */
+ if (cfl_list_size(&span->events) == 0) {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- events: none\n", min, "");
+ sds_cat_safe(buf, tmp);
+ }
+ else {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- events: ", min, "");
+ sds_cat_safe(buf, tmp);
+
+ cfl_list_foreach(head, &span->events) {
+ event = cfl_list_entry(head, struct ctrace_span_event, _head);
+ format_event(buf, event, min);
+ }
+ }
+
+ /* links */
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- [links]\n", min, "");
+ sds_cat_safe(buf, tmp);
+
+ cfl_list_foreach(head, &span->links) {
+ link = cfl_list_entry(head, struct ctrace_link, _head);
+
+ off = min + 4;
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- link:\n", off, "");
+ sds_cat_safe(buf, tmp);
+
+ off += 4;
+
+ /* trace_id */
+ if (link->trace_id) {
+ id_hex = ctr_id_to_lower_base16(link->trace_id);
+ }
+ else {
+ id_hex = cfl_sds_create(CTR_ID_TRACE_DEFAULT);
+ }
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- trace_id : %s\n", off, "", id_hex);
+ sds_cat_safe(buf, tmp);
+ cfl_sds_destroy(id_hex);
+
+ /* span_id */
+ if (link->span_id) {
+ id_hex = ctr_id_to_lower_base16(link->span_id);
+ }
+ else {
+ id_hex = cfl_sds_create(CTR_ID_SPAN_DEFAULT);
+ }
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- span_id : %s\n", off, "", id_hex);
+ sds_cat_safe(buf, tmp);
+ cfl_sds_destroy(id_hex);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- trace_state : %s\n", off, "", link->trace_state);
+ sds_cat_safe(buf, tmp);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- dropped_events_count : %" PRIu32 "\n", off, "", link->dropped_attr_count);
+ sds_cat_safe(buf, tmp);
+
+ /* link attributes */
+ if (!link->attr) {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- attributes : none\n", off, "");
+ sds_cat_safe(buf, tmp);
+ }
+ else {
+ snprintf(tmp, sizeof(tmp) - 1, "%*s- attributes : ", off, "");
+ sds_cat_safe(buf, tmp);
+ format_attributes(buf, span->attr->kv, off);
+ }
+ }
+}
+
+static void format_spans(cfl_sds_t *buf, struct ctrace *ctx, struct cfl_list *spans)
+{
+ struct cfl_list *head;
+ struct ctrace_span *span;
+
+ cfl_sds_printf(buf, " [spans]\n");
+
+ /* look for spans that belongs to the given resource */
+ cfl_list_foreach(head, spans){
+ span = cfl_list_entry(head, struct ctrace_span, _head);
+
+ /* skip resource if there is no match */
+ format_span(buf, ctx, span, 2);
+ }
+}
+
+static void format_instrumentation_scope(cfl_sds_t *buf,
+ struct ctrace_instrumentation_scope *scope)
+{
+ cfl_sds_printf(buf, " instrumentation scope:\n");
+ cfl_sds_printf(buf, " - name : %s\n", scope->name);
+ cfl_sds_printf(buf, " - version : %s\n", scope->version);
+ cfl_sds_printf(buf, " - dropped_attributes_count: %i\n", scope->dropped_attr_count);
+
+ if (scope->attr) {
+ cfl_sds_printf(buf, " - attributes:\n");
+ format_attributes(buf, scope->attr->kv, 8);
+ }
+ else {
+ cfl_sds_printf(buf, " - attributes: undefined\n");
+ }
+}
+
+static void format_resource(cfl_sds_t *buf, struct ctrace *ctx, struct ctrace_resource *resource)
+{
+ cfl_sds_printf(buf, " resource:\n");
+ cfl_sds_printf(buf, " - attributes:");
+ format_attributes(buf, resource->attr->kv, 8);
+ cfl_sds_printf(buf, " - dropped_attributes_count: %" PRIu32 "\n", resource->dropped_attr_count);
+}
+
+static void format_scope_spans(cfl_sds_t *buf, struct ctrace *ctx, struct cfl_list *scope_spans)
+{
+ struct cfl_list *head;
+ struct ctrace_scope_span *scope_span;
+
+ cfl_list_foreach(head, scope_spans) {
+ scope_span = cfl_list_entry(head, struct ctrace_scope_span, _head);
+
+ cfl_sds_printf(buf, " [scope_span]\n");
+
+ /* format 'instrumentation_scope' if set */
+ if (scope_span->instrumentation_scope) {
+ format_instrumentation_scope(buf, scope_span->instrumentation_scope);
+ }
+
+ /* schema_url */
+ if (scope_span->schema_url) {
+ cfl_sds_printf(buf, " schema_url: %s\n", scope_span->schema_url);
+ }
+ else {
+ cfl_sds_printf(buf, " schema_url: \"\"\n");
+ }
+
+ /* spans */
+ format_spans(buf, ctx, &scope_span->spans);
+ }
+}
+
+cfl_sds_t ctr_encode_text_create(struct ctrace *ctx)
+{
+ cfl_sds_t buf;
+ struct cfl_list *head;
+ struct ctrace_resource_span *resource_span;
+
+ buf = cfl_sds_create_size(1024);
+ if (!buf) {
+ return NULL;
+ }
+
+ /* iterate resource_spans */
+ cfl_list_foreach(head, &ctx->resource_spans) {
+ resource_span = cfl_list_entry(head, struct ctrace_resource_span, _head);
+
+ sds_cat_safe(&buf, "|-------------------- RESOURCE SPAN --------------------|\n");
+
+ if (resource_span->resource) {
+ format_resource(&buf, ctx, resource_span->resource);
+ }
+ else {
+ cfl_sds_printf(&buf, " resource: {}\n");
+ }
+
+ /* schema_url */
+ if (resource_span->schema_url) {
+ cfl_sds_printf(&buf, " schema_url: %s\n", resource_span->schema_url);
+ }
+ else {
+ cfl_sds_printf(&buf, " schema_url: \"\"\n");
+ }
+
+ /* scope spans */
+ format_scope_spans(&buf, ctx, &resource_span->scope_spans);
+ }
+
+ return buf;
+}
+
+void ctr_encode_text_destroy(cfl_sds_t text)
+{
+ cfl_sds_destroy(text);
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_id.c b/fluent-bit/lib/ctraces/src/ctr_id.c
new file mode 100644
index 000000000..0c2299fcd
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_id.c
@@ -0,0 +1,255 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+/* create an ID with random bytes of length CTR_ID_BUFFER_SIZE (16 bytes) */
+struct ctrace_id *ctr_id_create_random(size_t size)
+{
+ char *buf;
+ ssize_t ret;
+ struct ctrace_id *cid;
+
+ if (size <= 0) {
+ size = CTR_ID_DEFAULT_SIZE;
+ }
+
+ buf = calloc(1, size);
+ if (!buf) {
+ ctr_errno();
+ return NULL;
+ }
+
+ ret = ctr_random_get(buf, size);
+ if (ret < 0) {
+ free(buf);
+ return NULL;
+ }
+
+ cid = ctr_id_create(buf, size);
+ free(buf);
+
+ return cid;
+}
+
+void ctr_id_destroy(struct ctrace_id *cid)
+{
+ cfl_sds_destroy(cid->buf);
+ free(cid);
+}
+
+struct ctrace_id *ctr_id_create(void *buf, size_t len)
+{
+ int ret;
+ struct ctrace_id *cid;
+
+ if (len <= 0) {
+ return NULL;
+ }
+
+ cid = calloc(1, sizeof(struct ctrace_id));
+ if (!cid) {
+ ctr_errno();
+ return NULL;
+ }
+
+ ret = ctr_id_set(cid, buf, len);
+ if (ret == -1) {
+ free(cid);
+ return NULL;
+ }
+
+ return cid;
+}
+
+int ctr_id_set(struct ctrace_id *cid, void *buf, size_t len)
+{
+ if (cid->buf) {
+ cfl_sds_destroy(cid->buf);
+ }
+
+ cid->buf = cfl_sds_create_len(buf, len);
+ if (!cid->buf) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int ctr_id_cmp(struct ctrace_id *cid1, struct ctrace_id *cid2)
+{
+ int len1;
+ int len2;
+
+ if (!cid1 || !cid2) {
+ return -1;
+ }
+
+ len1 = cfl_sds_len(cid1->buf);
+ len2 = cfl_sds_len(cid2->buf);
+
+ if (len1 != len2) {
+ return -1;
+ }
+
+ if (memcmp(cid1->buf, cid2->buf, len1) == 0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+size_t ctr_id_get_len(struct ctrace_id *cid)
+{
+ return cfl_sds_len(cid->buf);
+}
+
+void *ctr_id_get_buf(struct ctrace_id *cid)
+{
+ return cid->buf;
+}
+
+cfl_sds_t ctr_id_to_lower_base16(struct ctrace_id *cid)
+{
+ int i;
+ int len;
+ cfl_sds_t out;
+ const char hex[] = "0123456789abcdef";
+
+ if (!cid->buf) {
+ return NULL;
+ }
+
+ len = cfl_sds_len(cid->buf);
+ out = cfl_sds_create_size(len * 2 + 1);
+ if (!out) {
+ return NULL;
+ }
+
+ for (i = 0; i < len; i++) {
+ out[i * 2] = hex[(cid->buf[i] >> 4) & 0xF];
+ out[i * 2 + 1] = hex[(cid->buf[i] >> 0) & 0xF];
+ }
+
+ out[i * 2] = 0;
+
+ return out;
+}
+
+/* This function returns CFL_TRUE on success and CFL_FALSE on
+ * failure.
+ */
+static int decode_hex_digit(char *digit)
+{
+ if (*digit >= '0' && *digit <= '9') {
+ *digit -= '0';
+ }
+ else if (*digit >= 'a' && *digit <= 'f') {
+ *digit -= 'a';
+ *digit += 10;
+ }
+ else if (*digit >= 'A' && *digit <= 'F') {
+ *digit -= 'A';
+ *digit += 10;
+ }
+ else {
+ return CFL_FALSE;
+ }
+
+ return CFL_TRUE;
+}
+
+struct ctrace_id *ctr_id_from_base16(cfl_sds_t id)
+{
+ size_t output_index;
+ size_t input_index;
+ cfl_sds_t decoded_id;
+ struct ctrace_id *result_id;
+ int result;
+ size_t length;
+ char digit;
+ char value;
+
+ if (id == NULL) {
+ return NULL;
+ }
+
+ length = cfl_sds_len(id);
+
+ if (length < 2) {
+ return NULL;
+ }
+
+ if ((length % 2) != 0) {
+ return NULL;
+ }
+
+ decoded_id = cfl_sds_create_size(length / 2);
+
+ if (decoded_id == NULL) {
+ return NULL;
+ }
+
+ output_index = 0;
+ input_index = 0;
+ value = 0;
+
+ /* This loop consumes one character per iteration,
+ * on each iteration it verifies that the character
+ * corresponds to the base16 charset and then
+ * it subtracts the correct base to get a number
+ * ranging from 0 to 16.
+ * Then the accumulator is left shifted 4 bits and
+ * the current value is bitwise ORed to its value.
+ * If the character index is odd then the accumulator
+ * value is appended to the decoded id buffer and
+ * reinitialized to be used on the next iteration.
+ */
+
+ while (input_index < length) {
+ digit = id[input_index];
+ result = decode_hex_digit(&digit);
+
+ if (!result) {
+ break;
+ }
+
+ digit &= 0xF;
+ value <<= 4;
+ value |= digit;
+
+ if ((input_index % 2) == 1) {
+ decoded_id[output_index++] = value;
+ value = 0;
+ }
+
+ input_index++;
+ }
+
+ if (result) {
+ result_id = ctr_id_create(decoded_id, length / 2);
+ }
+ else {
+ result_id = NULL;
+ }
+
+ cfl_sds_destroy(decoded_id);
+
+ return result_id;
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_link.c b/fluent-bit/lib/ctraces/src/ctr_link.c
new file mode 100644
index 000000000..9f92c3aa5
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_link.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+struct ctrace_link *ctr_link_create(struct ctrace_span *span,
+ void *trace_id_buf, size_t trace_id_len,
+ void *span_id_buf, size_t span_id_len)
+{
+ struct ctrace_link *link;
+
+ link = calloc(1, sizeof(struct ctrace_link));
+ if (!link) {
+ ctr_errno();
+ return NULL;
+ }
+
+ /* trace_id */
+ if (trace_id_buf && trace_id_len > 0) {
+ link->trace_id = ctr_id_create(trace_id_buf, trace_id_len);
+ if (!link->trace_id) {
+ free(link);
+ return NULL;
+ }
+ }
+
+ /* span_id */
+ if (span_id_buf && span_id_len > 0) {
+ link->span_id = ctr_id_create(span_id_buf, span_id_len);
+ if (!link->span_id) {
+ ctr_id_destroy(link->trace_id);
+ free(link);
+ return NULL;
+ }
+ }
+
+ cfl_list_add(&link->_head, &span->links);
+ return link;
+}
+
+struct ctrace_link *ctr_link_create_with_cid(struct ctrace_span *span,
+ struct ctrace_id *trace_id_cid,
+ struct ctrace_id *span_id_cid)
+{
+ size_t trace_id_len = 0;
+ size_t span_id_len = 0;
+ void *trace_id_buf = NULL;
+ void *span_id_buf = NULL;
+
+ if (trace_id_cid) {
+ trace_id_buf = ctr_id_get_buf(trace_id_cid);
+ trace_id_len = ctr_id_get_len(trace_id_cid);
+ }
+
+ if (span_id_cid) {
+ span_id_buf = ctr_id_get_buf(span_id_cid);
+ span_id_len = ctr_id_get_len(span_id_cid);
+ }
+
+ return ctr_link_create(span, trace_id_buf, trace_id_len, span_id_buf, span_id_len);
+}
+
+int ctr_link_set_trace_state(struct ctrace_link *link, char *trace_state)
+{
+ if (!link || !trace_state) {
+ return -1;
+ }
+
+ link->trace_state = cfl_sds_create(trace_state);
+ if (!link->trace_state) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int ctr_link_set_attributes(struct ctrace_link *link, struct ctrace_attributes *attr)
+{
+ if (!attr) {
+ return -1;
+ }
+
+ link->attr = attr;
+ return 0;
+}
+
+void ctr_link_set_dropped_attr_count(struct ctrace_link *link, uint32_t count)
+{
+ link->dropped_attr_count = count;
+}
+
+void ctr_link_destroy(struct ctrace_link *link)
+{
+ if (link->trace_id) {
+ ctr_id_destroy(link->trace_id);
+ }
+
+ if (link->span_id) {
+ ctr_id_destroy(link->span_id);
+ }
+
+ if (link->trace_state) {
+ cfl_sds_destroy(link->trace_state);
+ }
+
+ if (link->attr) {
+ ctr_attributes_destroy(link->attr);
+ }
+
+ cfl_list_del(&link->_head);
+ free(link);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fluent-bit/lib/ctraces/src/ctr_log.c b/fluent-bit/lib/ctraces/src/ctr_log.c
new file mode 100644
index 000000000..d09e11d3a
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_log.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+ #define strerror_r(errnum, buf, buf_size) strerror_s(buf, buf_size, errnum)
+#endif
+
+void ctr_log_print(void *ctx, int level, const char *file, int line,
+ const char *fmt, ...)
+{
+ int ret;
+ char buf[CTR_LOG_BUF_SIZE];
+ va_list args;
+ struct ctrace *ctr = ctx;
+
+ if (!ctr->log_cb) {
+ return;
+ }
+
+ if (level > ctr->log_level) {
+ return;
+ }
+
+ va_start(args, fmt);
+ ret = vsnprintf(buf, CTR_LOG_BUF_SIZE - 1, fmt, args);
+
+ if (ret >= 0) {
+ buf[ret] = '\0';
+ }
+ va_end(args);
+
+ ctr->log_cb(ctx, level, file, line, buf);
+}
+
+int ctr_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 ctr_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/ctraces/src/ctr_mpack_utils.c b/fluent-bit/lib/ctraces/src/ctr_mpack_utils.c
new file mode 100644
index 000000000..222e2664f
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_mpack_utils.c
@@ -0,0 +1,488 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 Eduardo Silva <eduardo@calyptia.com>
+ *
+ * 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 <ctraces/ctr_mpack_utils.h>
+#include <cfl/cfl_sds.h>
+#include <mpack/mpack.h>
+
+int ctr_mpack_consume_string_or_nil_tag(mpack_reader_t *reader, cfl_sds_t *output_buffer)
+{
+ int result;
+
+ if (ctr_mpack_peek_type(reader) == mpack_type_str) {
+ result = ctr_mpack_consume_string_tag(reader, output_buffer);
+ }
+ else if (ctr_mpack_peek_type(reader) == mpack_type_nil) {
+ result = ctr_mpack_consume_nil_tag(reader);
+
+ *output_buffer = NULL;
+ }
+ else {
+ result = CTR_MPACK_UNEXPECTED_DATA_TYPE_ERROR;
+ }
+
+ return result;
+}
+
+int ctr_mpack_consume_binary_or_nil_tag(mpack_reader_t *reader, cfl_sds_t *output_buffer)
+{
+ int result;
+
+ if (ctr_mpack_peek_type(reader) == mpack_type_bin) {
+ result = ctr_mpack_consume_binary_tag(reader, output_buffer);
+ }
+ else if (ctr_mpack_peek_type(reader) == mpack_type_nil) {
+ result = ctr_mpack_consume_nil_tag(reader);
+
+ *output_buffer = NULL;
+ }
+ else {
+ result = CTR_MPACK_UNEXPECTED_DATA_TYPE_ERROR;
+ }
+
+ return result;
+}
+
+int ctr_mpack_consume_nil_tag(mpack_reader_t *reader)
+{
+ mpack_tag_t tag;
+
+ if (NULL == reader) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ tag = mpack_read_tag(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_nil != mpack_tag_type(&tag)) {
+ return CTR_MPACK_UNEXPECTED_DATA_TYPE_ERROR;
+ }
+
+ return CTR_MPACK_SUCCESS;
+}
+
+int ctr_mpack_consume_double_tag(mpack_reader_t *reader, double *output_buffer)
+{
+ mpack_tag_t tag;
+
+ if (NULL == output_buffer) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ if (NULL == reader) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ tag = mpack_read_tag(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_double != mpack_tag_type(&tag)) {
+ return CTR_MPACK_UNEXPECTED_DATA_TYPE_ERROR;
+ }
+
+ *output_buffer = mpack_tag_double_value(&tag);
+
+ return CTR_MPACK_SUCCESS;
+}
+
+int ctr_mpack_consume_uint_tag(mpack_reader_t *reader, uint64_t *output_buffer)
+{
+ mpack_tag_t tag;
+
+ if (NULL == output_buffer) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ if (NULL == reader) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ tag = mpack_read_tag(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_int == mpack_tag_type(&tag)) {
+ *output_buffer = (uint64_t) mpack_tag_int_value(&tag);
+ }
+ else if (mpack_type_uint == mpack_tag_type(&tag)) {
+ *output_buffer = (uint64_t) mpack_tag_uint_value(&tag);
+ }
+ else {
+ return CTR_MPACK_UNEXPECTED_DATA_TYPE_ERROR;
+ }
+
+ return CTR_MPACK_SUCCESS;
+}
+
+int ctr_mpack_consume_uint32_tag(mpack_reader_t *reader, uint32_t *output_buffer)
+{
+ int result;
+ uint64_t value;
+
+ result = ctr_mpack_consume_uint_tag(reader, &value);
+
+ if (result == CTR_MPACK_SUCCESS) {
+ *output_buffer = (uint32_t) value;
+ }
+
+ return result;
+}
+
+int ctr_mpack_consume_uint64_tag(mpack_reader_t *reader, uint64_t *output_buffer)
+{
+ return ctr_mpack_consume_uint_tag(reader, output_buffer);
+}
+
+int ctr_mpack_consume_int_tag(mpack_reader_t *reader, int64_t *output_buffer)
+{
+ mpack_tag_t tag;
+
+ if (NULL == output_buffer) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ if (NULL == reader) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ tag = mpack_read_tag(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_int == mpack_tag_type(&tag)) {
+ *output_buffer = (int64_t) mpack_tag_int_value(&tag);
+ }
+ else if (mpack_type_uint == mpack_tag_type(&tag)) {
+ *output_buffer = (int64_t) mpack_tag_uint_value(&tag);
+ }
+ else {
+ return CTR_MPACK_UNEXPECTED_DATA_TYPE_ERROR;
+ }
+
+ return CTR_MPACK_SUCCESS;
+}
+
+int ctr_mpack_consume_int32_tag(mpack_reader_t *reader, int32_t *output_buffer)
+{
+ int result;
+ int64_t value;
+
+ result = ctr_mpack_consume_int_tag(reader, &value);
+
+ if (result == CTR_MPACK_SUCCESS) {
+ *output_buffer = (int32_t) value;
+ }
+
+ return result;
+}
+
+int ctr_mpack_consume_int64_tag(mpack_reader_t *reader, int64_t *output_buffer)
+{
+ return ctr_mpack_consume_int_tag(reader, output_buffer);
+}
+
+int ctr_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 CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ if (NULL == reader) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ tag = mpack_read_tag(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_str != mpack_tag_type(&tag)) {
+ return CTR_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 (CTR_MPACK_MAX_STRING_LENGTH < string_length) {
+ return CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ *output_buffer = cfl_sds_create_size(string_length + 1);
+
+ if (NULL == *output_buffer) {
+ return CTR_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 CTR_MPACK_ENGINE_ERROR;
+ }
+
+ mpack_done_str(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ cfl_sds_destroy(*output_buffer);
+
+ *output_buffer = NULL;
+
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ return CTR_MPACK_SUCCESS;
+}
+
+int ctr_mpack_consume_binary_tag(mpack_reader_t *reader, cfl_sds_t *output_buffer)
+{
+ uint32_t string_length;
+ mpack_tag_t tag;
+
+ if (NULL == output_buffer) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ if (NULL == reader) {
+ return CTR_MPACK_INVALID_ARGUMENT_ERROR;
+ }
+
+ tag = mpack_read_tag(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_bin != mpack_tag_type(&tag)) {
+ return CTR_MPACK_UNEXPECTED_DATA_TYPE_ERROR;
+ }
+
+ string_length = mpack_tag_bin_length(&tag);
+
+ *output_buffer = cfl_sds_create_size(string_length);
+
+ if (NULL == *output_buffer) {
+ return CTR_MPACK_ALLOCATION_ERROR;
+ }
+
+ cfl_sds_set_len(*output_buffer, string_length);
+
+ mpack_read_bytes(reader, *output_buffer, string_length);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ cfl_sds_destroy(*output_buffer);
+
+ *output_buffer = NULL;
+
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ mpack_done_bin(reader);
+
+ if (mpack_ok != mpack_reader_error(reader)) {
+ cfl_sds_destroy(*output_buffer);
+
+ *output_buffer = NULL;
+
+ return CTR_MPACK_ENGINE_ERROR;
+ }
+
+ return CTR_MPACK_SUCCESS;
+}
+
+int ctr_mpack_unpack_map(mpack_reader_t *reader,
+ struct ctr_mpack_map_entry_callback_t *callback_list,
+ void *context)
+{
+ struct ctr_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 CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_map != mpack_tag_type(&tag)) {
+ return CTR_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 CTR_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 (CTR_MPACK_MAX_MAP_ENTRY_COUNT < entry_count) {
+ return CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ result = 0;
+
+ for (entry_index = 0 ; 0 == result && entry_index < entry_count ; entry_index++) {
+ result = ctr_mpack_consume_string_tag(reader, &key_name);
+
+ if (CTR_MPACK_SUCCESS == result) {
+ callback_entry = callback_list;
+ result = CTR_MPACK_UNEXPECTED_KEY_ERROR;
+
+ while (CTR_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 (CTR_MPACK_SUCCESS == result) {
+ mpack_done_map(reader);
+
+ if (mpack_ok != mpack_reader_error(reader))
+ {
+ return CTR_MPACK_PENDING_MAP_ENTRIES;
+ }
+ }
+
+ return result;
+}
+
+int ctr_mpack_unpack_array(mpack_reader_t *reader,
+ ctr_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 CTR_MPACK_ENGINE_ERROR;
+ }
+
+ if (mpack_type_array != mpack_tag_type(&tag)) {
+ return CTR_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 (CTR_MPACK_MAX_ARRAY_ENTRY_COUNT < entry_count) {
+ return CTR_MPACK_CORRUPT_INPUT_DATA_ERROR;
+ }
+
+ result = CTR_MPACK_SUCCESS;
+
+ for (entry_index = 0 ;
+ CTR_MPACK_SUCCESS == result && entry_index < entry_count ;
+ entry_index++) {
+ result = entry_processor_callback(reader, entry_index, context);
+ }
+
+ if (CTR_MPACK_SUCCESS == result) {
+ mpack_done_array(reader);
+
+ if (mpack_ok != mpack_reader_error(reader))
+ {
+ return CTR_MPACK_PENDING_ARRAY_ENTRIES;
+ }
+ }
+
+ return result;
+}
+
+int ctr_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);
+}
+
+mpack_type_t ctr_mpack_peek_type(mpack_reader_t *reader)
+{
+ mpack_tag_t tag;
+
+ tag = mpack_peek_tag(reader);
+
+ if (mpack_reader_error(reader) != mpack_ok) {
+ return mpack_type_missing;
+ }
+
+ return mpack_tag_type(&tag);
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_random.c b/fluent-bit/lib/ctraces/src/ctr_random.c
new file mode 100644
index 000000000..0274c238b
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_random.c
@@ -0,0 +1,86 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+#if defined(unix) || defined (__unix) || defined(__unix__) || defined(__linux__) || \
+ defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__)
+#define ITS_A_UNIX_FRIEND
+#endif
+
+#ifdef CTR_HAVE_GETRANDOM
+#include <sys/random.h>
+#endif
+
+#ifdef ITS_A_UNIX_FRIEND
+#include <fcntl.h>
+#include <unistd.h>
+#else
+// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the
+// "Community Additions" comment on MSDN here:
+// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
+#define SystemFunction036 NTAPI SystemFunction036
+#include <ntsecapi.h>
+#undef SystemFunction036
+
+#endif
+
+#include <time.h>
+
+ssize_t ctr_random_get(void *buf, size_t len)
+{
+ int i;
+ ssize_t ret = 0;
+ unsigned int s;
+ char *tmp;
+
+#ifdef CTR_HAVE_GETRANDOM
+ /*
+ * On Linux systems getrandom() is preferred, note that our use case it's pretty
+ * simple (no security stuff).
+ */
+ ret = getrandom(buf, len, GRND_NONBLOCK);
+ return ret;
+#endif
+
+ /* if getrandom() is not available and we are on Linux, macOS or BSD, try out /dev/urandom */
+#ifdef ITS_A_UNIX_FRIEND
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd > 0) {
+ ret = read(fd, buf, len);
+ close(fd);
+ return ret;
+ }
+
+ s = time(NULL);
+
+ /* fallback... a very slow way to compose a random buffer */
+ tmp = buf;
+ for (i = 0; i < len; i++) {
+ /* fixme: we need a good entropy here */
+ tmp[i] = rand_r(&s);
+ }
+#else /* Windows ? */
+ ret = RtlGenRandom(buf, len);
+#endif
+
+ return ret;
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_resource.c b/fluent-bit/lib/ctraces/src/ctr_resource.c
new file mode 100644
index 000000000..718ef7bc4
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_resource.c
@@ -0,0 +1,159 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+#include <ctraces/ctr_resource.h>
+
+struct ctrace_resource *ctr_resource_create()
+{
+ struct ctrace_resource *res;
+ struct ctrace_attributes *attr;
+
+ res = calloc(1, sizeof(struct ctrace_resource));
+ if (!res) {
+ ctr_errno();
+ return NULL;
+ }
+
+ attr = ctr_attributes_create();
+ if (!attr) {
+ ctr_resource_destroy(res);
+ return NULL;
+ }
+ res->attr = attr;
+
+ return res;
+}
+
+struct ctrace_resource *ctr_resource_create_default()
+{
+ struct ctrace_resource *res;
+
+ res = ctr_resource_create();
+ if (!res) {
+ return NULL;
+ }
+
+ /* some default attributes */
+ ctr_attributes_set_string(res->attr, "service.name", "Fluent Bit");
+ ctr_attributes_set_int64(res->attr, "release_year", 2014);
+
+ return res;
+}
+
+int ctr_resource_set_attributes(struct ctrace_resource *res, struct ctrace_attributes *attr)
+{
+ if (!attr) {
+ return -1;
+ }
+
+ if (res->attr) {
+ ctr_attributes_destroy(res->attr);
+ }
+
+ res->attr = attr;
+ return 0;
+}
+
+void ctr_resource_set_dropped_attr_count(struct ctrace_resource *res, uint32_t count)
+{
+ res->dropped_attr_count = count;
+}
+
+void ctr_resource_destroy(struct ctrace_resource *res)
+{
+ if (res->attr) {
+ ctr_attributes_destroy(res->attr);
+ }
+ free(res);
+}
+
+/*
+ * resource_span API
+ * -----------------
+ */
+
+/* creates a resource_span context */
+struct ctrace_resource_span *ctr_resource_span_create(struct ctrace *ctx)
+{
+ struct ctrace_resource_span *resource_span;
+
+ resource_span = calloc(1, sizeof(struct ctrace_resource_span));
+ if (!resource_span) {
+ ctr_errno();
+ return NULL;
+ }
+ cfl_list_init(&resource_span->scope_spans);
+
+ /* link to ctraces context */
+ cfl_list_add(&resource_span->_head, &ctx->resource_spans);
+
+ /* create an empty resource */
+ resource_span->resource = ctr_resource_create();
+ if (!resource_span->resource) {
+ free(resource_span);
+ return NULL;
+ }
+
+ return resource_span;
+}
+
+struct ctrace_resource *ctr_resource_span_get_resource(struct ctrace_resource_span *resource_span)
+{
+ return resource_span->resource;
+}
+
+/* Set the schema_url for a resource_span */
+int ctr_resource_span_set_schema_url(struct ctrace_resource_span *resource_span, char *url)
+{
+ if (resource_span->schema_url) {
+ cfl_sds_destroy(resource_span->schema_url);
+ }
+
+ resource_span->schema_url = cfl_sds_create(url);
+ if (!resource_span->schema_url) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void ctr_resource_span_destroy(struct ctrace_resource_span *resource_span)
+{
+ struct cfl_list *tmp;
+ struct cfl_list *head;
+ struct ctrace_scope_span *scope_span;
+
+ /* release resource if set */
+ if (resource_span->resource) {
+ ctr_resource_destroy(resource_span->resource);
+ }
+
+ if (resource_span->schema_url) {
+ cfl_sds_destroy(resource_span->schema_url);
+ }
+
+ /* remove scope spans */
+ cfl_list_foreach_safe(head, tmp, &resource_span->scope_spans) {
+ scope_span = cfl_list_entry(head, struct ctrace_scope_span, _head);
+ ctr_scope_span_destroy(scope_span);
+ }
+
+ free(resource_span);
+}
diff --git a/fluent-bit/lib/ctraces/src/ctr_scope.c b/fluent-bit/lib/ctraces/src/ctr_scope.c
new file mode 100644
index 000000000..fcb83435a
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_scope.c
@@ -0,0 +1,129 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+struct ctrace_scope_span *ctr_scope_span_create(struct ctrace_resource_span *resource_span)
+{
+ struct ctrace_scope_span *scope_span;
+
+ scope_span = calloc(1, sizeof(struct ctrace_scope_span));
+ if (!scope_span) {
+ ctr_errno();
+ return NULL;
+ }
+ cfl_list_init(&scope_span->spans);
+ cfl_list_add(&scope_span->_head, &resource_span->scope_spans);
+
+ return scope_span;
+}
+
+void ctr_scope_span_destroy(struct ctrace_scope_span *scope_span)
+{
+ struct cfl_list *tmp;
+ struct cfl_list *head;
+ struct ctrace_span *span;
+
+ /* release instrumentation scope if set */
+ if (scope_span->instrumentation_scope) {
+ ctr_instrumentation_scope_destroy(scope_span->instrumentation_scope);
+ }
+
+ /* remove linked spans */
+ cfl_list_foreach_safe(head, tmp, &scope_span->spans) {
+ span = cfl_list_entry(head, struct ctrace_span, _head);
+ ctr_span_destroy(span);
+ }
+
+ if (scope_span->schema_url) {
+ cfl_sds_destroy(scope_span->schema_url);
+ }
+
+ cfl_list_del(&scope_span->_head);
+ free(scope_span);
+}
+
+/* Set the schema_url for a resource_span */
+int ctr_scope_span_set_schema_url(struct ctrace_scope_span *scope_span, char *url)
+{
+ if (scope_span->schema_url) {
+ cfl_sds_destroy(scope_span->schema_url);
+ }
+
+ scope_span->schema_url = cfl_sds_create(url);
+ if (!scope_span->schema_url) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void ctr_scope_span_set_instrumentation_scope(struct ctrace_scope_span *scope_span,
+ struct ctrace_instrumentation_scope *scope)
+{
+ /* Safeguard against leaks */
+ if (scope_span->instrumentation_scope != NULL) {
+ ctr_instrumentation_scope_destroy(scope_span->instrumentation_scope);
+ }
+
+ scope_span->instrumentation_scope = scope;
+}
+
+struct ctrace_instrumentation_scope *ctr_instrumentation_scope_create(char *name, char *version,
+ uint32_t dropped_attr_count,
+ struct ctrace_attributes *attr)
+{
+ struct ctrace_instrumentation_scope *ins_scope;
+
+ ins_scope = calloc(1, sizeof(struct ctrace_instrumentation_scope));
+ if (!ins_scope) {
+ ctr_errno();
+ return NULL;
+ }
+
+ if (name) {
+ ins_scope->name = cfl_sds_create(name);
+ }
+ if (version) {
+ ins_scope->version = cfl_sds_create(version);
+ }
+
+ ins_scope->dropped_attr_count = dropped_attr_count;
+ ins_scope->attr = attr;
+
+ return ins_scope;
+}
+
+void ctr_instrumentation_scope_destroy(struct ctrace_instrumentation_scope *ins_scope)
+{
+ if (ins_scope->name) {
+ cfl_sds_destroy(ins_scope->name);
+ }
+
+ if (ins_scope->version) {
+ cfl_sds_destroy(ins_scope->version);
+ }
+
+ if (ins_scope->attr) {
+ ctr_attributes_destroy(ins_scope->attr);
+ }
+
+ free(ins_scope);
+}
+
diff --git a/fluent-bit/lib/ctraces/src/ctr_span.c b/fluent-bit/lib/ctraces/src/ctr_span.c
new file mode 100644
index 000000000..d93935a72
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_span.c
@@ -0,0 +1,434 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+#include <cfl/cfl.h>
+#include <cfl/cfl_time.h>
+#include <cfl/cfl_kvlist.h>
+
+struct ctrace_span *ctr_span_create(struct ctrace *ctx, struct ctrace_scope_span *scope_span, cfl_sds_t name,
+ struct ctrace_span *parent)
+{
+ struct ctrace_span *span;
+
+ if (!ctx || !scope_span || !name) {
+ return NULL;
+ }
+
+ /* allocate a spanc context */
+ span = calloc(1, sizeof(struct ctrace_span));
+ if (!span) {
+ ctr_errno();
+ return NULL;
+ }
+
+ /* references */
+ span->scope_span = scope_span;
+ span->ctx = ctx;
+
+ /* name */
+ span->name = cfl_sds_create(name);
+ if (!span->name) {
+ free(span);
+ return NULL;
+ }
+
+ /* attributes */
+ span->attr = ctr_attributes_create();
+ if (!span->attr) {
+ free(span);
+ return NULL;
+ }
+ cfl_list_init(&span->events);
+ cfl_list_init(&span->links);
+
+ /* dropped attributes count */
+ span->dropped_attr_count = 0;
+
+ /* if a parent context was given, populate the span parent id */
+ if (parent && parent->span_id) {
+ ctr_span_set_parent_span_id_with_cid(span, parent->span_id);
+ }
+
+ /* link span to struct scope_span->spans */
+ cfl_list_add(&span->_head, &scope_span->spans);
+
+ /* link span to the struct ctrace->span_list */
+ cfl_list_add(&span->_head_global, &ctx->span_list);
+
+ /* set default kind */
+ ctr_span_kind_set(span, CTRACE_SPAN_INTERNAL);
+
+ /* always start a span by default, the start can be overriden later if needed */
+ ctr_span_start(ctx, span);
+ return span;
+}
+
+/* Set the Span ID with a given buffer and length */
+int ctr_span_set_trace_id(struct ctrace_span *span, void *buf, size_t len)
+{
+ if (!buf || len <= 0) {
+ return -1;
+ }
+
+ /* If trace_id is already set, free it first */
+ if (span->trace_id != NULL) {
+ ctr_id_destroy(span->trace_id);
+ span->trace_id = NULL;
+ }
+
+ span->trace_id = ctr_id_create(buf, len);
+ if (!span->trace_id) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Set the Span ID by using a ctrace_id context */
+int ctr_span_set_trace_id_with_cid(struct ctrace_span *span, struct ctrace_id *cid)
+{
+ return ctr_span_set_trace_id(span,
+ ctr_id_get_buf(cid),
+ ctr_id_get_len(cid));
+}
+
+/* Set the Span ID with a given buffer and length */
+int ctr_span_set_span_id(struct ctrace_span *span, void *buf, size_t len)
+{
+ if (!buf || len <= 0) {
+ return -1;
+ }
+
+ span->span_id = ctr_id_create(buf, len);
+ if (!span->span_id) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Set the Span ID by using a ctrace_id context */
+int ctr_span_set_span_id_with_cid(struct ctrace_span *span, struct ctrace_id *cid)
+{
+ return ctr_span_set_span_id(span,
+ ctr_id_get_buf(cid),
+ ctr_id_get_len(cid));
+}
+
+/* Set the Span Parent ID with a given buffer and length */
+int ctr_span_set_parent_span_id(struct ctrace_span *span, void *buf, size_t len)
+{
+ if (!buf || len <= 0) {
+ return -1;
+ }
+
+ if (span->parent_span_id) {
+ ctr_id_destroy(span->parent_span_id);
+ }
+
+ span->parent_span_id = ctr_id_create(buf, len);
+ if (!span->parent_span_id) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Set the Span ID by using a ctrace_id context */
+int ctr_span_set_parent_span_id_with_cid(struct ctrace_span *span, struct ctrace_id *cid)
+{
+ return ctr_span_set_parent_span_id(span,
+ ctr_id_get_buf(cid),
+ ctr_id_get_len(cid));
+}
+
+int ctr_span_kind_set(struct ctrace_span *span, int kind)
+{
+ if (kind < CTRACE_SPAN_UNSPECIFIED || kind > CTRACE_SPAN_CONSUMER) {
+ return -1;
+ }
+
+ span->kind = kind;
+ return 0;
+}
+
+/* returns a read-only version of the Span kind */
+char *ctr_span_kind_string(struct ctrace_span *span)
+{
+ switch (span->kind) {
+ case CTRACE_SPAN_INTERNAL:
+ return "internal";
+ case CTRACE_SPAN_SERVER:
+ return "server";
+ case CTRACE_SPAN_CLIENT:
+ return "client";
+ case CTRACE_SPAN_PRODUCER:
+ return "producer";
+ case CTRACE_SPAN_CONSUMER:
+ return "consumer";
+ default:
+ return "unspecified";
+ };
+}
+
+/*
+ * Span attributes
+ * ---------------
+ */
+int ctr_span_set_attribute_string(struct ctrace_span *span, char *key, char *value)
+{
+ return ctr_attributes_set_string(span->attr, key, value);
+}
+
+int ctr_span_set_attribute_bool(struct ctrace_span *span, char *key, int b)
+{
+ return ctr_attributes_set_bool(span->attr, key, b);
+}
+
+int ctr_span_set_attribute_int64(struct ctrace_span *span, char *key, int64_t value)
+{
+ return ctr_attributes_set_int64(span->attr, key, value);
+}
+
+int ctr_span_set_attribute_double(struct ctrace_span *span, char *key, double value)
+{
+ return ctr_attributes_set_double(span->attr, key, value);
+}
+
+int ctr_span_set_attribute_array(struct ctrace_span *span, char *key,
+ struct cfl_array *value)
+{
+ return ctr_attributes_set_array(span->attr, key, value);
+}
+
+int ctr_span_set_attribute_kvlist(struct ctrace_span *span, char *key,
+ struct cfl_kvlist *value)
+{
+
+ return ctr_attributes_set_kvlist(span->attr, key, value);
+}
+
+void ctr_span_start(struct ctrace *ctx, struct ctrace_span *span)
+{
+ uint64_t ts;
+
+ ts = cfl_time_now();
+ ctr_span_start_ts(ctx, span, ts);
+}
+
+void ctr_span_start_ts(struct ctrace *ctx, struct ctrace_span *span, uint64_t ts)
+{
+ /* set the initial timestamp */
+ span->start_time_unix_nano = ts;
+
+ /* always set the span end time as the start time, so duration can be zero */
+ ctr_span_end_ts(ctx, span, ts);
+}
+
+void ctr_span_end(struct ctrace *ctx, struct ctrace_span *span)
+{
+ uint64_t ts;
+
+ ts = cfl_time_now();
+ ctr_span_end_ts(ctx, span, ts);
+}
+
+void ctr_span_end_ts(struct ctrace *ctx, struct ctrace_span *span, uint64_t ts)
+{
+ span->end_time_unix_nano = ts;
+}
+
+int ctr_span_set_status(struct ctrace_span *span, int code, char *message)
+{
+ struct ctrace_span_status *status;
+
+ status = &span->status;
+ if (status->message) {
+ cfl_sds_destroy(status->message);
+ }
+
+ if (message) {
+ status->message = cfl_sds_create(message);
+ if (!status->message) {
+ return -1;
+ }
+ }
+
+ status->code = code;
+ return 0;
+}
+
+void ctr_span_set_dropped_events_count(struct ctrace_span *span, uint32_t count)
+{
+ span->dropped_events_count = count;
+}
+
+void ctr_span_set_dropped_attributes_count(struct ctrace_span *span, uint32_t count)
+{
+ span->dropped_attr_count = count;
+}
+
+void ctr_span_destroy(struct ctrace_span *span)
+{
+ struct cfl_list *tmp;
+ struct cfl_list *head;
+ struct ctrace_span_event *event;
+ struct ctrace_span_status *status;
+ struct ctrace_link *link;
+
+ if (span->name) {
+ cfl_sds_destroy(span->name);
+ }
+
+ if (span->trace_id) {
+ ctr_id_destroy(span->trace_id);
+ }
+
+ if (span->span_id) {
+ ctr_id_destroy(span->span_id);
+ }
+
+ if (span->parent_span_id) {
+ ctr_id_destroy(span->parent_span_id);
+ }
+
+ /* attributes */
+ if (span->attr) {
+ ctr_attributes_destroy(span->attr);
+ }
+
+ /* events */
+ cfl_list_foreach_safe(head, tmp, &span->events) {
+ event = cfl_list_entry(head, struct ctrace_span_event, _head);
+ ctr_span_event_delete(event);
+ }
+
+ /* links */
+ cfl_list_foreach_safe(head, tmp, &span->links) {
+ link = cfl_list_entry(head, struct ctrace_link, _head);
+ ctr_link_destroy(link);
+ }
+
+ /* status */
+ status = &span->status;
+ if (status->message) {
+ cfl_sds_destroy(status->message);
+ }
+
+ cfl_list_del(&span->_head);
+ cfl_list_del(&span->_head_global);
+ free(span);
+}
+
+/*
+ * Span Events
+ * -----------
+ */
+struct ctrace_span_event *ctr_span_event_add_ts(struct ctrace_span *span, char *name, uint64_t ts)
+{
+ struct ctrace_span_event *ev;
+
+ if (!name) {
+ return NULL;
+ }
+
+ ev = calloc(1, sizeof(struct ctrace_span_event));
+ if (!ev) {
+ ctr_errno();
+ return NULL;
+ }
+ ev->name = cfl_sds_create(name);
+ if (!ev->name) {
+ free(ev);
+ return NULL;
+ }
+ ev->attr = ctr_attributes_create(128);
+ ev->dropped_attr_count = 0;
+
+ /* if no timestamp is given, use the current time */
+ if (ts == 0) {
+ ev->time_unix_nano = cfl_time_now();
+ }
+ else {
+ ev->time_unix_nano = ts;
+ }
+
+ cfl_list_add(&ev->_head, &span->events);
+ return ev;
+}
+
+struct ctrace_span_event *ctr_span_event_add(struct ctrace_span *span, char *name)
+{
+ return ctr_span_event_add_ts(span, name, 0);
+}
+
+int ctr_span_event_set_attribute_string(struct ctrace_span_event *event, char *key, char *value)
+{
+ return ctr_attributes_set_string(event->attr, key, value);
+}
+
+int ctr_span_event_set_attribute_bool(struct ctrace_span_event *event, char *key, int b)
+{
+ return ctr_attributes_set_bool(event->attr, key, b);
+}
+
+int ctr_span_event_set_attribute_int64(struct ctrace_span_event *event, char *key, int64_t value)
+{
+ return ctr_attributes_set_int64(event->attr, key, value);
+}
+
+int ctr_span_event_set_attribute_double(struct ctrace_span_event *event, char *key, double value)
+{
+ return ctr_attributes_set_double(event->attr, key, value);
+}
+
+int ctr_span_event_set_attribute_array(struct ctrace_span_event *event, char *key,
+ struct cfl_array *value)
+{
+ return ctr_attributes_set_array(event->attr, key, value);
+}
+
+int ctr_span_event_set_attribute_kvlist(struct ctrace_span_event *event, char *key,
+ struct cfl_kvlist *value)
+{
+
+ return ctr_attributes_set_kvlist(event->attr, key, value);
+}
+
+void ctr_span_event_set_dropped_attributes_count(struct ctrace_span_event *event, uint32_t count)
+{
+ event->dropped_attr_count = count;
+}
+
+void ctr_span_event_delete(struct ctrace_span_event *event)
+{
+ if (event->name) {
+ cfl_sds_destroy(event->name);
+ }
+
+ if (event->attr) {
+ ctr_attributes_destroy(event->attr);
+ }
+
+ cfl_list_del(&event->_head);
+ free(event);
+}
+
diff --git a/fluent-bit/lib/ctraces/src/ctr_utils.c b/fluent-bit/lib/ctraces/src/ctr_utils.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_utils.c
diff --git a/fluent-bit/lib/ctraces/src/ctr_version.c b/fluent-bit/lib/ctraces/src/ctr_version.c
new file mode 100644
index 000000000..923e6d89b
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctr_version.c
@@ -0,0 +1,26 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+
+char *ctr_version()
+{
+ return CTR_VERSION_STR;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/ctraces/src/ctraces.c b/fluent-bit/lib/ctraces/src/ctraces.c
new file mode 100644
index 000000000..d2258be5d
--- /dev/null
+++ b/fluent-bit/lib/ctraces/src/ctraces.c
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* CTraces
+ * =======
+ * Copyright 2022 The CTraces 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 <ctraces/ctraces.h>
+
+void ctr_opts_init(struct ctrace_opts *opts)
+{
+ memset(opts, '\0', sizeof(struct ctrace_opts));
+}
+
+void ctr_opts_set(struct ctrace_opts *opts, int value, char *val)
+{
+ /* unused */
+ (void) opts;
+ (void) value;
+ (void) val;
+}
+
+void ctr_opts_exit(struct ctrace_opts *opts)
+{
+ if (!opts) {
+ return;
+ }
+}
+
+/* Create a CTrace context */
+struct ctrace *ctr_create(struct ctrace_opts *opts)
+{
+ struct ctrace *ctx;
+
+ ctx = calloc(1, sizeof(struct ctrace));
+ if (!ctx) {
+ ctr_errno();
+ return NULL;
+ }
+ cfl_list_init(&ctx->resource_spans);
+ cfl_list_init(&ctx->span_list);
+
+ return ctx;
+}
+
+void ctr_destroy(struct ctrace *ctx)
+{
+ struct cfl_list *head;
+ struct cfl_list *tmp;
+ struct ctrace_resource_span *resource_span;
+
+ /* delete resources */
+ cfl_list_foreach_safe(head, tmp, &ctx->resource_spans) {
+ resource_span = cfl_list_entry(head, struct ctrace_resource_span, _head);
+ ctr_resource_span_destroy(resource_span);
+ }
+
+ free(ctx);
+}
+