Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 189 additions & 0 deletions ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#pragma once

#include <chrono>
#include <mutex>
#include <unordered_map>
#include <vector>

#include "opentelemetry/core/timestamp.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/sdk/trace/recordable.h"
#include "opentelemetry/trace/canonical_code.h"
#include "opentelemetry/trace/span.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include "opentelemetry/trace/span_id.h"
#include "opentelemetry/trace/trace_id.h"

using opentelemetry::sdk::trace::AttributeConverter;
using opentelemetry::sdk::trace::SpanDataAttributeValue;
using opentelemetry::sdk::trace::SpanDataEvent;
namespace trace_api = opentelemetry::trace;

OPENTELEMETRY_BEGIN_NAMESPACE
namespace ext {
namespace zpages {

/**
* This class is a threadsafe version of span data used for zpages in OT
*/
class ThreadsafeSpanData final : public opentelemetry::sdk::trace::Recordable {
public:
/**
* Get the trace id for this span
* @return the trace id for this span
*/
opentelemetry::trace::TraceId GetTraceId() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return trace_id_;
}

/**
* Get the span id for this span
* @return the span id for this span
*/
opentelemetry::trace::SpanId GetSpanId() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return span_id_;
}

/**
* Get the parent span id for this span
* @return the span id for this span's parent
*/
opentelemetry::trace::SpanId GetParentSpanId() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return parent_span_id_;
}

/**
* Get the name for this span
* @return the name for this span
*/
opentelemetry::nostd::string_view GetName() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return name_;
}

/**
* Get the status for this span
* @return the status for this span
*/
opentelemetry::trace::CanonicalCode GetStatus() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return status_code_;
}

/**
* Get the status description for this span
* @return the description of the the status of this span
*/
opentelemetry::nostd::string_view GetDescription() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return status_desc_;
}

/**
* Get the start time for this span
* @return the start time for this span
*/
opentelemetry::core::SystemTimestamp GetStartTime() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return start_time_;
}

/**
* Get the duration for this span
* @return the duration for this span
*/
std::chrono::nanoseconds GetDuration() const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
return duration_;
}

/**
* Get the attributes for this span
* @return the attributes for this span
*/
const std::unordered_map<std::string, SpanDataAttributeValue> GetAttributes()
const noexcept {
std::lock_guard<std::mutex> lock(mutex_);
Comment thread
kmanghat marked this conversation as resolved.
return attributes_;
}

void SetIds(opentelemetry::trace::TraceId trace_id,
opentelemetry::trace::SpanId span_id,
opentelemetry::trace::SpanId parent_span_id) noexcept override {
std::lock_guard<std::mutex> lock(mutex_);
trace_id_ = trace_id;
span_id_ = span_id;
parent_span_id_ = parent_span_id;
}

void SetAttribute(nostd::string_view key,
const common::AttributeValue &value) noexcept override {
std::lock_guard<std::mutex> lock(mutex_);
attributes_[std::string(key)] = nostd::visit(converter_, value);
}

void SetStatus(trace_api::CanonicalCode code,
nostd::string_view description) noexcept override {
std::lock_guard<std::mutex> lock(mutex_);
status_code_ = code;
status_desc_ = std::string(description);
}

void SetName(nostd::string_view name) noexcept override {
std::lock_guard<std::mutex> lock(mutex_);
name_ = std::string(name);
}

void SetStartTime(
opentelemetry::core::SystemTimestamp start_time) noexcept override {
std::lock_guard<std::mutex> lock(mutex_);
start_time_ = start_time;
}

void SetDuration(std::chrono::nanoseconds duration) noexcept override {
std::lock_guard<std::mutex> lock(mutex_);
duration_ = duration;
}

void AddLink(
opentelemetry::trace::SpanContext span_context,
const trace_api::KeyValueIterable &attributes =
trace_api::KeyValueIterableView<std::map<std::string, int>>({})) noexcept override
{
std::lock_guard<std::mutex> lock(mutex_);
(void)span_context;
(void)attributes;
}

void AddEvent(
nostd::string_view name,
core::SystemTimestamp timestamp = core::SystemTimestamp(std::chrono::system_clock::now()),
const trace_api::KeyValueIterable &attributes =
trace_api::KeyValueIterableView<std::map<std::string, int>>({})) noexcept override
{
std::lock_guard<std::mutex> lock(mutex_);
events_.push_back(SpanDataEvent(std::string(name), timestamp));
// TODO: handle attributes
}

private:
mutable std::mutex mutex_;
opentelemetry::trace::TraceId trace_id_;
opentelemetry::trace::SpanId span_id_;
opentelemetry::trace::SpanId parent_span_id_;
core::SystemTimestamp start_time_;
std::chrono::nanoseconds duration_{0};
std::string name_;
opentelemetry::trace::CanonicalCode status_code_{
opentelemetry::trace::CanonicalCode::OK};
std::string status_desc_;
std::unordered_map<std::string, SpanDataAttributeValue> attributes_;
std::vector<SpanDataEvent> events_;
AttributeConverter converter_;
};
} // namespace zpages
} // namespace ext
OPENTELEMETRY_END_NAMESPACE
12 changes: 12 additions & 0 deletions ext/test/zpages/BUILD
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
cc_test(
name = "threadsafe_span_data_tests",
srcs = [
"threadsafe_span_data_test.cc",
],
deps = [
"//sdk/src/trace",
"//ext/src/zpages",
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "tracez_processor_tests",
srcs = [
Expand Down
2 changes: 1 addition & 1 deletion ext/test/zpages/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
foreach(testname
tracez_processor_test)
tracez_processor_test threadsafe_span_data_test)
add_executable(${testname} "${testname}.cc")
target_link_libraries(
${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
Expand Down
55 changes: 55 additions & 0 deletions ext/test/zpages/threadsafe_span_data_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "opentelemetry/ext/zpages/threadsafe_span_data.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/trace/span_id.h"
#include "opentelemetry/trace/trace_id.h"

#include <gtest/gtest.h>
#include <thread>

using opentelemetry::sdk::trace::AttributeConverter;
using opentelemetry::sdk::trace::SpanDataAttributeValue;
using opentelemetry::ext::zpages::ThreadsafeSpanData;

TEST(ThreadsafeSpanData, DefaultValues)
{
opentelemetry::trace::TraceId zero_trace_id;
opentelemetry::trace::SpanId zero_span_id;
ThreadsafeSpanData data;

ASSERT_EQ(data.GetTraceId(), zero_trace_id);
ASSERT_EQ(data.GetSpanId(), zero_span_id);
ASSERT_EQ(data.GetParentSpanId(), zero_span_id);
ASSERT_EQ(data.GetName(), "");
ASSERT_EQ(data.GetStatus(), opentelemetry::trace::CanonicalCode::OK);
ASSERT_EQ(data.GetDescription(), "");
ASSERT_EQ(data.GetStartTime().time_since_epoch(), std::chrono::nanoseconds(0));
ASSERT_EQ(data.GetDuration(), std::chrono::nanoseconds(0));
ASSERT_EQ(data.GetAttributes().size(), 0);
}

TEST(ThreadsafeSpanData, Set)
{
opentelemetry::trace::TraceId trace_id;
opentelemetry::trace::SpanId span_id;
opentelemetry::trace::SpanId parent_span_id;
opentelemetry::core::SystemTimestamp now(std::chrono::system_clock::now());

ThreadsafeSpanData data;
data.SetIds(trace_id, span_id, parent_span_id);
data.SetName("span name");
data.SetStatus(opentelemetry::trace::CanonicalCode::UNKNOWN, "description");
data.SetStartTime(now);
data.SetDuration(std::chrono::nanoseconds(1000000));
data.SetAttribute("attr1", 314159);
data.AddEvent("event1", now);

ASSERT_EQ(data.GetTraceId(), trace_id);
ASSERT_EQ(data.GetSpanId(), span_id);
ASSERT_EQ(data.GetParentSpanId(), parent_span_id);
ASSERT_EQ(data.GetName(), "span name");
ASSERT_EQ(data.GetStatus(), opentelemetry::trace::CanonicalCode::UNKNOWN);
ASSERT_EQ(data.GetDescription(), "description");
ASSERT_EQ(data.GetStartTime().time_since_epoch(), now.time_since_epoch());
ASSERT_EQ(data.GetDuration(), std::chrono::nanoseconds(1000000));
ASSERT_EQ(opentelemetry::nostd::get<int64_t>(data.GetAttributes().at("attr1")), 314159);
}