]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/jaegertracing/opentelemetry-cpp/exporters/jaeger/test/jaeger_recordable_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / exporters / jaeger / test / jaeger_recordable_test.cc
diff --git a/ceph/src/jaegertracing/opentelemetry-cpp/exporters/jaeger/test/jaeger_recordable_test.cc b/ceph/src/jaegertracing/opentelemetry-cpp/exporters/jaeger/test/jaeger_recordable_test.cc
new file mode 100644 (file)
index 0000000..4a0a1f7
--- /dev/null
@@ -0,0 +1,334 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include <vector>
+#include "opentelemetry/exporters/jaeger/recordable.h"
+#include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h"
+#include "opentelemetry/sdk/trace/simple_processor.h"
+#include "opentelemetry/sdk/trace/span_data.h"
+#include "opentelemetry/sdk/trace/tracer_provider.h"
+#include "opentelemetry/trace/provider.h"
+
+#include <gtest/gtest.h>
+
+namespace trace    = opentelemetry::trace;
+namespace nostd    = opentelemetry::nostd;
+namespace sdktrace = opentelemetry::sdk::trace;
+namespace common   = opentelemetry::common;
+
+using namespace jaegertracing;
+using namespace opentelemetry::exporter::jaeger;
+using namespace opentelemetry::sdk::instrumentationlibrary;
+using std::vector;
+
+using Attributes = std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>;
+
+TEST(JaegerSpanRecordable, SetIdentity)
+{
+  JaegerRecordable rec;
+
+  int64_t trace_id_val[2]    = {0x0000000000000000, 0x1000000000000000};
+  int64_t span_id_val        = 0x2000000000000000;
+  int64_t parent_span_id_val = 0x3000000000000000;
+
+  const trace::TraceId trace_id{
+      nostd::span<uint8_t, 16>(reinterpret_cast<uint8_t *>(trace_id_val), 16)};
+
+  const trace::SpanId span_id(
+      nostd::span<uint8_t, 8>(reinterpret_cast<uint8_t *>(&span_id_val), 8));
+
+  const trace::SpanId parent_span_id(
+      nostd::span<uint8_t, 8>(reinterpret_cast<uint8_t *>(&parent_span_id_val), 8));
+
+  const trace::SpanContext span_context{trace_id, span_id,
+                                        trace::TraceFlags{trace::TraceFlags::kIsSampled}, true};
+  rec.SetIdentity(span_context, parent_span_id);
+
+  std::unique_ptr<thrift::Span> span{rec.Span()};
+
+#if JAEGER_IS_LITTLE_ENDIAN == 1
+  EXPECT_EQ(span->traceIdLow, otel_bswap_64(trace_id_val[1]));
+  EXPECT_EQ(span->traceIdHigh, otel_bswap_64(trace_id_val[0]));
+  EXPECT_EQ(span->spanId, otel_bswap_64(span_id_val));
+  EXPECT_EQ(span->parentSpanId, otel_bswap_64(parent_span_id_val));
+#else
+  EXPECT_EQ(span->traceIdLow, trace_id_val[0]);
+  EXPECT_EQ(span->traceIdHigh, trace_id_val[1]);
+  EXPECT_EQ(span->spanId, span_id_val);
+  EXPECT_EQ(span->parentSpanId, parent_span_id_val);
+#endif
+}
+
+TEST(JaegerSpanRecordable, SetName)
+{
+  JaegerRecordable rec;
+
+  nostd::string_view name = "Test Span";
+  rec.SetName(name);
+
+  std::unique_ptr<thrift::Span> span{rec.Span()};
+
+  EXPECT_EQ(span->operationName, name);
+}
+
+TEST(JaegerSpanRecordable, SetStartTime)
+{
+  JaegerRecordable rec;
+
+  std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now();
+  common::SystemTimestamp start_timestamp(start_time);
+  uint64_t unix_start =
+      std::chrono::duration_cast<std::chrono::microseconds>(start_time.time_since_epoch()).count();
+  rec.SetStartTime(start_timestamp);
+
+  std::unique_ptr<thrift::Span> span{rec.Span()};
+
+  EXPECT_EQ(span->startTime, unix_start);
+}
+
+TEST(JaegerSpanRecordable, SetDuration)
+{
+  JaegerRecordable rec;
+
+  common::SystemTimestamp start_timestamp;
+
+  std::chrono::microseconds duration(10);
+  uint64_t unix_end = duration.count();
+
+  rec.SetStartTime(start_timestamp);
+  rec.SetDuration(duration);
+
+  std::unique_ptr<thrift::Span> span{rec.Span()};
+
+  EXPECT_EQ(span->startTime, 0);
+  EXPECT_EQ(span->duration, unix_end);
+}
+
+TEST(JaegerSpanRecordable, SetStatus)
+{
+  JaegerRecordable rec;
+
+  const char *error_description = "Error test";
+  rec.SetStatus(trace::StatusCode::kError, error_description);
+
+  auto tags = rec.Tags();
+  EXPECT_EQ(tags.size(), 3);
+
+  EXPECT_EQ(tags[0].key, "otel.status_code");
+  EXPECT_EQ(tags[0].vType, thrift::TagType::STRING);
+  EXPECT_EQ(tags[0].vStr, "ERROR");
+
+  EXPECT_EQ(tags[1].key, "error");
+  EXPECT_EQ(tags[1].vType, thrift::TagType::BOOL);
+  EXPECT_EQ(tags[1].vBool, true);
+
+  EXPECT_EQ(tags[2].key, "otel.status_description");
+  EXPECT_EQ(tags[2].vType, thrift::TagType::STRING);
+  EXPECT_EQ(tags[2].vStr, error_description);
+}
+
+TEST(JaegerSpanRecordable, AddEvent)
+{
+  JaegerRecordable rec;
+
+  std::chrono::system_clock::time_point event_time = std::chrono::system_clock::now();
+  common::SystemTimestamp event_timestamp(event_time);
+  uint64_t epoch_us =
+      std::chrono::duration_cast<std::chrono::microseconds>(event_time.time_since_epoch()).count();
+
+  const int kNumAttributes                  = 3;
+  std::string keys[kNumAttributes]          = {"attr1", "attr2", "attr3"};
+  int64_t values[kNumAttributes]            = {4, 7, 23};
+  std::map<std::string, int64_t> attributes = {
+      {keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}};
+
+  rec.AddEvent("Test Event", event_timestamp,
+               common::KeyValueIterableView<std::map<std::string, int64_t>>(attributes));
+  thrift::Log log = rec.Logs().at(0);
+  EXPECT_EQ(log.timestamp, epoch_us);
+  auto tags    = log.fields;
+  size_t index = 0;
+  EXPECT_EQ(tags[index].key, "event");
+  EXPECT_EQ(tags[index++].vStr, "Test Event");
+  while (index <= kNumAttributes)
+  {
+    EXPECT_EQ(tags[index].key, keys[index - 1]);
+    EXPECT_EQ(tags[index].vLong, values[index - 1]);
+    index++;
+  }
+}
+
+template <typename value_type>
+void addTag(thrift::TagType::type tag_type,
+            const std::string &key,
+            value_type value,
+            vector<thrift::Tag> &tags)
+{
+  thrift::Tag tag;
+
+  tag.__set_key(key);
+  tag.__set_vType(tag_type);
+  if (tag_type == thrift::TagType::LONG)
+  {
+    tag.__set_vLong(static_cast<int64_t>(value));
+  }
+  else if (tag_type == thrift::TagType::DOUBLE)
+  {
+    tag.__set_vDouble(static_cast<double>(value));
+  }
+  else if (tag_type == thrift::TagType::BOOL)
+  {
+    tag.__set_vBool(static_cast<bool>(value));
+  }
+
+  tags.push_back(tag);
+}
+
+void addTag(const std::string &key, std::string value, vector<thrift::Tag> &tags)
+{
+  thrift::Tag tag;
+
+  tag.__set_key(key);
+  tag.__set_vType(thrift::TagType::STRING);
+  tag.__set_vStr(value);
+
+  tags.push_back(tag);
+}
+
+TEST(JaegerSpanRecordable, SetAttributes)
+{
+  JaegerRecordable rec;
+  std::string string_val{"string_val"};
+  vector<common::AttributeValue> values{
+      bool{false},
+      int32_t{-32},
+      int64_t{-64},
+      uint32_t{32},
+      double{3.14},
+      string_val.c_str(),
+      nostd::string_view{"string_view"},
+  };
+  for (const auto &val : values)
+  {
+    rec.SetAttribute("key1", val);
+  }
+  rec.SetAttribute("key2", nostd::span<const bool>{{false, true}});
+  rec.SetAttribute("key3", nostd::span<const int32_t>{{-320, 320}});
+  rec.SetAttribute("key4", nostd::span<const int64_t>{{-640, 640}});
+  rec.SetAttribute("key5", nostd::span<const uint32_t>{{320, 322}});
+  rec.SetAttribute("key6", nostd::span<const double>{{4.15, 5.15}});
+  rec.SetAttribute("key7", nostd::span<const nostd::string_view>{{"string_v1", "string_v2"}});
+
+  auto tags = rec.Tags();
+  EXPECT_EQ(tags.size(), values.size() + 12);
+
+  vector<thrift::Tag> expected_tags;
+  addTag(thrift::TagType::BOOL, "key1", bool{false}, expected_tags);
+  addTag(thrift::TagType::LONG, "key1", int32_t{-32}, expected_tags);
+  addTag(thrift::TagType::LONG, "key1", int64_t{-64}, expected_tags);
+  addTag(thrift::TagType::LONG, "key1", int32_t{32}, expected_tags);
+  addTag(thrift::TagType::DOUBLE, "key1", double{3.14}, expected_tags);
+  addTag("key1", string_val, expected_tags);
+  addTag("key1", std::string{"string_view"}, expected_tags);
+
+  addTag(thrift::TagType::BOOL, "key2", bool{false}, expected_tags);
+  addTag(thrift::TagType::BOOL, "key2", bool{true}, expected_tags);
+  addTag(thrift::TagType::LONG, "key3", int32_t{-320}, expected_tags);
+  addTag(thrift::TagType::LONG, "key3", int32_t{320}, expected_tags);
+  addTag(thrift::TagType::LONG, "key4", int64_t{-640}, expected_tags);
+  addTag(thrift::TagType::LONG, "key4", int64_t{640}, expected_tags);
+  addTag(thrift::TagType::LONG, "key5", uint32_t{320}, expected_tags);
+  addTag(thrift::TagType::LONG, "key5", uint32_t{322}, expected_tags);
+  addTag(thrift::TagType::DOUBLE, "key6", double{4.15}, expected_tags);
+  addTag(thrift::TagType::DOUBLE, "key6", double{5.15}, expected_tags);
+  addTag("key7", std::string{"string_v1"}, expected_tags);
+  addTag("key7", std::string{"string_v2"}, expected_tags);
+
+  EXPECT_EQ(tags, expected_tags);
+}
+
+TEST(JaegerSpanRecordable, SetInstrumentationLibrary)
+{
+  JaegerRecordable rec;
+
+  std::string library_name     = "opentelemetry-cpp";
+  std::string library_version  = "0.1.0";
+  auto instrumentation_library = InstrumentationLibrary::Create(library_name, library_version);
+
+  rec.SetInstrumentationLibrary(*instrumentation_library);
+
+  auto tags = rec.Tags();
+  EXPECT_EQ(tags.size(), 2);
+
+  EXPECT_EQ(tags[0].key, "otel.library.name");
+  EXPECT_EQ(tags[0].vType, thrift::TagType::STRING);
+  EXPECT_EQ(tags[0].vStr, library_name);
+
+  EXPECT_EQ(tags[1].key, "otel.library.version");
+  EXPECT_EQ(tags[1].vType, thrift::TagType::STRING);
+  EXPECT_EQ(tags[1].vStr, library_version);
+}
+
+TEST(JaegerSpanRecordable, SetResource)
+{
+  JaegerRecordable rec;
+
+  const std::string service_name_key = "service.name";
+  std::string service_name_value     = "test-jaeger-service-name";
+  auto resource                      = opentelemetry::sdk::resource::Resource::Create(
+      {{service_name_key, service_name_value}, {"key1", "value1"}, {"key2", "value2"}});
+  rec.SetResource(resource);
+
+  auto service_name  = rec.ServiceName();
+  auto resource_tags = rec.ResourceTags();
+
+  EXPECT_GE(resource_tags.size(), 2);
+  EXPECT_EQ(service_name, service_name_value);
+
+  for (const auto &tag : resource_tags)
+  {
+    if (tag.key == "key1")
+    {
+      EXPECT_EQ(tag.vType, thrift::TagType::STRING);
+      EXPECT_EQ(tag.vStr, "value1");
+    }
+    else if (tag.key == "key2")
+    {
+      EXPECT_EQ(tag.vType, thrift::TagType::STRING);
+      EXPECT_EQ(tag.vStr, "value2");
+    }
+  }
+}
+
+TEST(JaegerSpanRecordable, AddLink)
+{
+  JaegerRecordable rec;
+
+  int64_t trace_id_val[2] = {0x0000000000000000, 0x1000000000000000};
+  int64_t span_id_val     = 0x2000000000000000;
+
+  const trace::TraceId trace_id{
+      nostd::span<uint8_t, 16>(reinterpret_cast<uint8_t *>(trace_id_val), 16)};
+
+  const trace::SpanId span_id(
+      nostd::span<uint8_t, 8>(reinterpret_cast<uint8_t *>(&span_id_val), 8));
+
+  const trace::SpanContext span_context{trace_id, span_id,
+                                        trace::TraceFlags{trace::TraceFlags::kIsSampled}, true};
+  rec.AddLink(span_context, common::KeyValueIterableView<Attributes>({{"attr1", "string"}}));
+
+  auto references = rec.References();
+  EXPECT_EQ(references.size(), 1);
+
+  auto reference = references.front();
+
+#if JAEGER_IS_LITTLE_ENDIAN == 1
+  EXPECT_EQ(reference.traceIdLow, otel_bswap_64(trace_id_val[1]));
+  EXPECT_EQ(reference.traceIdHigh, otel_bswap_64(trace_id_val[0]));
+  EXPECT_EQ(reference.spanId, otel_bswap_64(span_id_val));
+#else
+  EXPECT_EQ(reference.traceIdLow, trace_id_val[0]);
+  EXPECT_EQ(reference.traceIdHigh, trace_id_val[1]);
+  EXPECT_EQ(reference.spanId, span_id_val);
+#endif
+}