summaryrefslogtreecommitdiffstats
path: root/src/span.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/span.cpp547
1 files changed, 547 insertions, 0 deletions
diff --git a/src/span.cpp b/src/span.cpp
new file mode 100644
index 0000000..3e9323d
--- /dev/null
+++ b/src/span.cpp
@@ -0,0 +1,547 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * 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 "include.h"
+
+
+#ifdef OT_THREADS_NO_LOCKING
+thread_local Handle<opentracing::Span> ot_span_handle;
+thread_local Handle<opentracing::SpanContext> ot_span_context_handle;
+struct HandleData ot_span;
+struct HandleData ot_span_context;
+#else
+struct Handle<opentracing::Span> ot_span;
+struct Handle<opentracing::SpanContext> ot_span_context;
+#endif /* OT_THREADS_NO_LOCKING */
+
+
+/***
+ * NAME
+ * ot_span_finish_with_options -
+ *
+ * ARGUMENTS
+ * span -
+ * options -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_finish_with_options(struct otc_span *span, const struct otc_finish_span_options *options)
+{
+ OT_LOCK_GUARD(span);
+
+ if (!OT_SPAN_IS_VALID(span))
+ return;
+
+ if (options == nullptr) {
+ ot_span_handle.at(span->idx)->Finish();
+ } else {
+ struct opentracing::FinishSpanOptions span_options;
+
+ if (options->finish_time.value.tv_sec > 0) {
+ auto dt = timespec_to_duration(&(options->finish_time.value));
+
+ span_options.finish_steady_timestamp = std::chrono::time_point<std::chrono::steady_clock>(dt);
+ }
+
+ if (options->log_records != nullptr) {
+ for (int i = 0; i < options->num_log_records; i++) {
+ struct opentracing::LogRecord record;
+
+ if (options->log_records[i].timestamp.value.tv_sec > 0) {
+#ifdef __clang__
+ auto dt = timespec_to_duration_us(&(options->log_records[i].timestamp.value));
+#else
+ auto dt = timespec_to_duration(&(options->log_records[i].timestamp.value));
+#endif
+
+ record.timestamp = std::chrono::time_point<std::chrono::system_clock>(dt);
+ }
+
+ for (int j = 0; j < options->log_records[i].num_fields; j++)
+ if (options->log_records[i].fields[j].value.type == otc_value_bool) {
+ record.fields.push_back(std::make_pair(options->log_records[i].fields[j].key, options->log_records[i].fields[j].value.value.bool_value));
+ }
+ else if (options->log_records[i].fields[j].value.type == otc_value_double) {
+ record.fields.push_back(std::make_pair(options->log_records[i].fields[j].key, options->log_records[i].fields[j].value.value.double_value));
+ }
+ else if (options->log_records[i].fields[j].value.type == otc_value_int64) {
+ record.fields.push_back(std::make_pair(options->log_records[i].fields[j].key, options->log_records[i].fields[j].value.value.int64_value));
+ }
+ else if (options->log_records[i].fields[j].value.type == otc_value_uint64) {
+ record.fields.push_back(std::make_pair(options->log_records[i].fields[j].key, options->log_records[i].fields[j].value.value.uint64_value));
+ }
+ else if (options->log_records[i].fields[j].value.type == otc_value_string) {
+ std::string str_value = options->log_records[i].fields[j].value.value.string_value;
+
+ record.fields.push_back(std::make_pair(options->log_records[i].fields[j].key, str_value));
+ }
+ else if (options->log_records[i].fields[j].value.type == otc_value_null) {
+ record.fields.push_back(std::make_pair(options->log_records[i].fields[j].key, nullptr));
+ }
+
+ span_options.log_records.push_back(record);
+ }
+ }
+
+ ot_span_handle.at(span->idx)->FinishWithOptions(span_options);
+ }
+
+ ot_nolock_span_destroy(&span);
+}
+
+
+/***
+ * NAME
+ * ot_span_finish -
+ *
+ * ARGUMENTS
+ * span -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_finish(struct otc_span *span)
+{
+ ot_span_finish_with_options(span, nullptr);
+}
+
+
+/***
+ * NAME
+ * ot_span_get_context -
+ *
+ * ARGUMENTS
+ * span -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * -
+ */
+static struct otc_span_context *ot_span_get_context(struct otc_span *span)
+{
+ OT_LOCK(span, span_context);
+
+ if (!OT_SPAN_IS_VALID(span))
+ return nullptr;
+
+ return ot_span_context_new(span);
+}
+
+
+/***
+ * NAME
+ * ot_span_set_operation_name -
+ *
+ * ARGUMENTS
+ * span -
+ * operation_name -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_set_operation_name(struct otc_span *span, const char *operation_name)
+{
+ OT_LOCK_GUARD(span);
+
+ if (!OT_SPAN_IS_VALID(span) || (operation_name == nullptr))
+ return;
+
+ ot_span_handle.at(span->idx)->SetOperationName(operation_name);
+}
+
+
+/***
+ * NAME
+ * ot_span_set_tag -
+ *
+ * ARGUMENTS
+ * span -
+ * key -
+ * value -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_set_tag(struct otc_span *span, const char *key, const struct otc_value *value)
+{
+ OT_LOCK_GUARD(span);
+
+ if (!OT_SPAN_IS_VALID(span) || (key == nullptr) || (value == nullptr))
+ return;
+
+ if (value->type == otc_value_bool) {
+ ot_span_handle.at(span->idx)->SetTag(key, value->value.bool_value);
+ }
+ else if (value->type == otc_value_double) {
+ ot_span_handle.at(span->idx)->SetTag(key, value->value.double_value);
+ }
+ else if (value->type == otc_value_int64) {
+ ot_span_handle.at(span->idx)->SetTag(key, value->value.int64_value);
+ }
+ else if (value->type == otc_value_uint64) {
+ ot_span_handle.at(span->idx)->SetTag(key, value->value.uint64_value);
+ }
+ else if (value->type == otc_value_string) {
+ std::string str_value = value->value.string_value;
+
+ ot_span_handle.at(span->idx)->SetTag(key, str_value);
+ }
+ else if (value->type == otc_value_null) {
+ ot_span_handle.at(span->idx)->SetTag(key, nullptr);
+ }
+ else {
+ /* Do nothing. */
+ }
+}
+
+
+/***
+ * NAME
+ * ot_span_log_fields -
+ *
+ * ARGUMENTS
+ * span -
+ * fields -
+ * num_fields -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_log_fields(struct otc_span *span, const struct otc_log_field *fields, int num_fields)
+{
+ OT_LOCK_GUARD(span);
+ std::string str_value[OTC_MAXLOGFIELDS];
+
+ if (!OT_SPAN_IS_VALID(span) || (fields == nullptr) || !OT_IN_RANGE(num_fields, 1, OTC_MAXLOGFIELDS))
+ return;
+
+ /* XXX The only data type supported in this function is string. */
+ for (int i = 0; (i < num_fields) && (i < OTC_MAXLOGFIELDS); i++) {
+ if (fields[i].value.type != otc_value_string)
+ str_value[i] = "invalid data type";
+ else if (fields[i].value.value.string_value != nullptr)
+ str_value[i] = fields[i].value.value.string_value;
+ else
+ str_value[i] = "";
+ }
+
+ if (num_fields == 1)
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0) });
+ else if (num_fields == 2)
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0), OT_LF(1) });
+ else if (num_fields == 3)
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0), OT_LF(1), OT_LF(2) });
+ else if (num_fields == 4)
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0), OT_LF(1), OT_LF(2), OT_LF(3) });
+ else if (num_fields == 5)
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0), OT_LF(1), OT_LF(2), OT_LF(3), OT_LF(4) });
+ else if (num_fields == 6)
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0), OT_LF(1), OT_LF(2), OT_LF(3), OT_LF(4), OT_LF(5) });
+ else if (num_fields == 7)
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0), OT_LF(1), OT_LF(2), OT_LF(3), OT_LF(4), OT_LF(5), OT_LF(6) });
+ else
+ ot_span_handle.at(span->idx)->Log({ OT_LF(0), OT_LF(1), OT_LF(2), OT_LF(3), OT_LF(4), OT_LF(5), OT_LF(6), OT_LF(7) });
+}
+
+
+/***
+ * NAME
+ * ot_span_set_baggage_item -
+ *
+ * ARGUMENTS
+ * span -
+ * key -
+ * value -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_set_baggage_item(struct otc_span *span, const char *key, const char *value)
+{
+ OT_LOCK_GUARD(span);
+
+ if (!OT_SPAN_IS_VALID(span) || (key == nullptr) || (value == nullptr))
+ return;
+
+ ot_span_handle.at(span->idx)->SetBaggageItem(key, value);
+}
+
+
+/***
+ * NAME
+ * ot_span_baggage_item -
+ *
+ * ARGUMENTS
+ * span -
+ * key -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * -
+ */
+static const char *ot_span_baggage_item(const struct otc_span *span, const char *key)
+{
+ OT_LOCK_GUARD(span);
+ const char *retptr = "";
+
+ if (!OT_SPAN_IS_VALID(span) || (key == nullptr))
+ return retptr;
+
+ auto baggage = ot_span_handle.at(span->idx)->BaggageItem(key);
+ if (!baggage.empty())
+ retptr = OTC_DBG_STRDUP(baggage.c_str());
+
+ return retptr;
+}
+
+
+/***
+ * NAME
+ * ot_span_tracer -
+ *
+ * ARGUMENTS
+ * span - NOT USED
+ *
+ * DESCRIPTION
+ * - NOT IMPLEMENTED
+ *
+ * RETURN VALUE
+ * -
+ */
+static struct otc_tracer *ot_span_tracer(const struct otc_span *span)
+{
+ struct otc_tracer *retptr = nullptr;
+
+ if (!OT_SPAN_IS_VALID(span))
+ return retptr;
+
+ return retptr;
+}
+
+
+/***
+ * NAME
+ * ot_nolock_span_destroy -
+ *
+ * ARGUMENTS
+ * span -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+void ot_nolock_span_destroy(struct otc_span **span)
+{
+ if ((span == nullptr) || ((*span) == nullptr))
+ return;
+
+ if (OT_SPAN_KEY_IS_VALID(*span)) {
+ ot_span_handle.erase((*span)->idx);
+ ot_span.erase_cnt++;
+ }
+
+ ot_span.destroy_cnt++;
+
+ OT_EXT_FREE_CLEAR(*span);
+}
+
+
+/***
+ * NAME
+ * ot_span_destroy -
+ *
+ * ARGUMENTS
+ * span -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_destroy(struct otc_span **span)
+{
+ OT_LOCK_GUARD(span);
+
+ ot_nolock_span_destroy(span);
+}
+
+
+/***
+ * NAME
+ * ot_span_new -
+ *
+ * ARGUMENTS
+ * This function takes no arguments.
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * -
+ */
+struct otc_span *ot_span_new(void)
+{
+ const static struct otc_span span_init = {
+ .idx = 0,
+ .finish = ot_span_finish, /* lock span */
+ .finish_with_options = ot_span_finish_with_options, /* lock span */
+ .span_context = ot_span_get_context, /* lock span and span_context */
+ .set_operation_name = ot_span_set_operation_name, /* lock span */
+ .set_tag = ot_span_set_tag, /* lock span */
+ .log_fields = ot_span_log_fields, /* lock span */
+ .set_baggage_item = ot_span_set_baggage_item, /* lock span */
+ .baggage_item = ot_span_baggage_item, /* lock span */
+ .tracer = ot_span_tracer, /* NOT IMPLEMENTED */
+ .destroy = ot_span_destroy /* lock span */
+ };
+ int64_t idx = ot_span.key++;
+ struct otc_span *retptr;
+
+ if (idx == 0) {
+ ot_span_handle.clear();
+ ot_span_handle.reserve(8192);
+ }
+
+ if ((retptr = OT_CAST_TYPEOF(retptr, OT_EXT_MALLOC(sizeof(*retptr)))) != nullptr) {
+ (void)memcpy(retptr, &span_init, sizeof(*retptr));
+ retptr->idx = idx;
+ } else {
+ ot_span.alloc_fail_cnt++;
+ }
+
+ return retptr;
+}
+
+
+/***
+ * NAME
+ * ot_nolock_span_context_destroy -
+ *
+ * ARGUMENTS
+ * context -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_nolock_span_context_destroy(struct otc_span_context **context)
+{
+ if ((context == nullptr) || (*context == nullptr))
+ return;
+
+ if (OT_CTX_KEY_IS_VALID(*context)) {
+ ot_span_context_handle.erase((*context)->idx);
+ ot_span_context.erase_cnt++;
+ }
+
+ ot_span_context.destroy_cnt++;
+
+ OT_EXT_FREE_CLEAR(*context);
+}
+
+
+/***
+ * NAME
+ * ot_span_context_destroy -
+ *
+ * ARGUMENTS
+ * context -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void ot_span_context_destroy(struct otc_span_context **context)
+{
+ OT_LOCK_GUARD(span_context);
+
+ ot_nolock_span_context_destroy(context);
+}
+
+
+/***
+ * NAME
+ * ot_span_context_new -
+ *
+ * ARGUMENTS
+ * span -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * -
+ */
+struct otc_span_context *ot_span_context_new(const struct otc_span *span)
+{
+ int64_t idx = ot_span_context.key++;
+ struct otc_span_context *retptr;
+
+ if (idx == 0) {
+ ot_span_context_handle.clear();
+ ot_span_context_handle.reserve(8192);
+ }
+
+ if ((retptr = OT_CAST_TYPEOF(retptr, OT_EXT_MALLOC(sizeof(*retptr)))) == nullptr) {
+ ot_span_context.alloc_fail_cnt++;
+
+ return retptr;
+ }
+
+ retptr->idx = (span == nullptr) ? idx : -1;
+ retptr->span = span;
+ retptr->destroy = ot_span_context_destroy; /* lock span_context */
+
+ return retptr;
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */