Skip to content

Commit

Permalink
zPages: Threadsafe recordable (open-telemetry#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
kmanghat authored Jul 28, 2020
1 parent 283114d commit de0033f
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 1 deletion.
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_);
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);
}

0 comments on commit de0033f

Please sign in to comment.