Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support adding links to span #351

Merged
merged 27 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 3 additions & 2 deletions api/include/opentelemetry/plugin/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ class Tracer final : public trace::Tracer, public std::enable_shared_from_this<T
nostd::shared_ptr<trace::Span> StartSpan(
nostd::string_view name,
const trace::KeyValueIterable &attributes,
const trace::StartSpanOptions &options = {}) noexcept override
const trace::StartSpanOptions &options = {},
const nostd::span<trace::Link> &links = {}) noexcept override
{
auto span = tracer_handle_->tracer().StartSpan(name, attributes, options);
auto span = tracer_handle_->tracer().StartSpan(name, attributes, options, links);
if (span == nullptr)
{
return nostd::shared_ptr<trace::Span>(nullptr);
Expand Down
49 changes: 49 additions & 0 deletions api/include/opentelemetry/trace/link.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#include <iostream>
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/trace/key_value_iterable_view.h"
#include "opentelemetry/trace/span_context.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace trace
{
class Link final
{
public:
Link() = default;

Link(const opentelemetry::trace::SpanContext &span_context,
const trace_api::KeyValueIterable &attributes)
: span_context_(span_context), attributes_(attributes)
{}

template <class T, nostd::enable_if_t<detail::is_key_value_iterable<T>::value> * = nullptr>
Link(const SpanContext &span_context, const T &attributes)
: Link(span_context, KeyValueIterableView<T>(attributes))
{}

Link(const SpanContext &span_context,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes)
: Link(span_context,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()})
{}

Link(const opentelemetry::trace::SpanContext &span_context)
: Link(span_context,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{})
{}

// returns the Span Context associated with this Link
const SpanContext &GetSpanContext() const { return span_context_; }

// returns the attributes associated with link
const KeyValueIterable &GetAttributes() const { return attributes_; }

private:
const trace_api::SpanContext &span_context_;
const trace_api::KeyValueIterable &attributes_;
lalitb marked this conversation as resolved.
Show resolved Hide resolved
};
} // namespace trace
OPENTELEMETRY_END_NAMESPACE
3 changes: 2 additions & 1 deletion api/include/opentelemetry/trace/noop.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class NoopTracer final : public Tracer, public std::enable_shared_from_this<Noop
// Tracer
nostd::shared_ptr<Span> StartSpan(nostd::string_view /*name*/,
const KeyValueIterable & /*attributes*/,
const StartSpanOptions & /*options*/) noexcept override
const StartSpanOptions & /*options*/,
const nostd::span<Link> & /*links*/) noexcept override
{
// Don't allocate a no-op span for every StartSpan call, but use a static
// singleton for this case.
Expand Down
16 changes: 10 additions & 6 deletions api/include/opentelemetry/trace/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/trace/default_span.h"
#include "opentelemetry/trace/link.h"
#include "opentelemetry/trace/scope.h"
#include "opentelemetry/trace/span.h"
#include "opentelemetry/version.h"
Expand Down Expand Up @@ -33,31 +34,34 @@ class Tracer
*/
virtual nostd::shared_ptr<Span> StartSpan(nostd::string_view name,
const KeyValueIterable &attributes,
const StartSpanOptions &options = {}) noexcept = 0;
const StartSpanOptions &options = {},
const nostd::span<Link> &links = {}) noexcept = 0;

nostd::shared_ptr<Span> StartSpan(nostd::string_view name,
const StartSpanOptions &options = {}) noexcept
{
return this->StartSpan(name, {}, options);
return this->StartSpan(name, {}, options, {});
}

template <class T, nostd::enable_if_t<detail::is_key_value_iterable<T>::value> * = nullptr>
nostd::shared_ptr<Span> StartSpan(nostd::string_view name,
const T &attributes,
const StartSpanOptions &options = {}) noexcept
const StartSpanOptions &options = {},
const nostd::span<Link> &links = {}) noexcept
{
return this->StartSpan(name, KeyValueIterableView<T>(attributes), options);
return this->StartSpan(name, KeyValueIterableView<T>(attributes), options, links);
}

nostd::shared_ptr<Span> StartSpan(
nostd::string_view name,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
const StartSpanOptions &options = {}) noexcept
const StartSpanOptions &options = {},
const nostd::span<Link> &links = {}) noexcept
{
return this->StartSpan(name,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
options);
options, links);
}

/**
Expand Down
11 changes: 11 additions & 0 deletions api/test/trace/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,14 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "link_test",
srcs = [
"link_test.cc",
],
deps = [
"//api",
"@com_google_googletest//:gtest_main",
],
)
3 changes: 2 additions & 1 deletion api/test/trace/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ foreach(
span_context_test
scope_test
noop_test
tracer_test)
tracer_test
link_test)
add_executable(api_${testname} "${testname}.cc")
target_link_libraries(api_${testname} ${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
Expand Down
59 changes: 59 additions & 0 deletions api/test/trace/link_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "opentelemetry/trace/link.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/trace/key_value_iterable_view.h"
#include "opentelemetry/trace/span_context.h"

#include <gtest/gtest.h>
#include <iostream>
#include <map>

using namespace opentelemetry;

using opentelemetry::trace::KeyValueIterable;
using opentelemetry::trace::KeyValueIterableView;
using opentelemetry::trace::Link;
using opentelemetry::trace::SpanContext;

using Map = std::map<nostd::string_view, nostd::string_view>;
void validateKeyValueIterableView(const KeyValueIterable &attributes, Map &keys)
{
attributes.ForEachKeyValue([&](nostd::string_view key,
opentelemetry::common::AttributeValue value) noexcept {
bool found = (keys.end() != keys.find(key));
EXPECT_EQ(found, true);
return true;
});
}

void validateKeyValueInitializationList(const KeyValueIterable &attributes,
const std::vector<nostd::string_view> &keys)
{
int i = 0;
attributes.ForEachKeyValue([&](nostd::string_view key,
opentelemetry::common::AttributeValue value) noexcept {
std::cout << key;
return true;
});
}
TEST(LinkTest, CreateLinkIterableView)
{

Map m1 = {{"abc", "123"}, {"xyz", "456"}};
SpanContext s1(true, true);
KeyValueIterableView<Map> iterable{m1};

Link link(s1, iterable);
validateKeyValueIterableView(link.GetAttributes(), m1);
EXPECT_EQ(s1.IsSampled(), link.GetSpanContext().IsSampled());
}

TEST(LinkTest, CreateLinkInitlilizerList)
{

SpanContext s1(true, true);
Link link1(s1, {{"k1", "v1"}, {"k2", "v2"}});

std::map<std::string, int> attributes = {{"attr1", 1}, {"attr2", 2}};
Link link2(s1, attributes);
}
8 changes: 5 additions & 3 deletions examples/plugin/plugin/tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class Span final : public trace::Span
Span(std::shared_ptr<Tracer> &&tracer,
nostd::string_view name,
const opentelemetry::trace::KeyValueIterable & /*attributes*/,
const trace::StartSpanOptions & /*options*/) noexcept
const trace::StartSpanOptions & /*options*/,
const nostd::span<trace::Link> & /*links*/) noexcept
: tracer_{std::move(tracer)}, name_{name}
{
std::cout << "StartSpan: " << name << "\n";
Expand Down Expand Up @@ -66,8 +67,9 @@ Tracer::Tracer(nostd::string_view /*output*/) {}
nostd::shared_ptr<trace::Span> Tracer::StartSpan(
nostd::string_view name,
const opentelemetry::trace::KeyValueIterable &attributes,
const trace::StartSpanOptions &options) noexcept
const trace::StartSpanOptions &options,
const nostd::span<trace::Link> &links) noexcept
{
return nostd::shared_ptr<opentelemetry::trace::Span>{
new (std::nothrow) Span{this->shared_from_this(), name, attributes, options}};
new (std::nothrow) Span{this->shared_from_this(), name, attributes, options, links}};
}
3 changes: 2 additions & 1 deletion examples/plugin/plugin/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class Tracer final : public opentelemetry::trace::Tracer,
opentelemetry::nostd::shared_ptr<opentelemetry::trace::Span> StartSpan(
opentelemetry::nostd::string_view name,
const opentelemetry::trace::KeyValueIterable & /*attributes*/,
const opentelemetry::trace::StartSpanOptions & /*options */) noexcept override;
const opentelemetry::trace::StartSpanOptions & /*options */,
const opentelemetry::nostd::span<opentelemetry::trace::Link> & /*links*/) noexcept override;

void ForceFlushWithMicroseconds(uint64_t /*timeout*/) noexcept override {}

Expand Down
3 changes: 2 additions & 1 deletion sdk/include/opentelemetry/sdk/trace/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class Tracer final : public trace_api::Tracer, public std::enable_shared_from_th
nostd::shared_ptr<trace_api::Span> StartSpan(
nostd::string_view name,
const trace_api::KeyValueIterable &attributes,
const trace_api::StartSpanOptions &options = {}) noexcept override;
const trace_api::StartSpanOptions &options = {},
const nostd::span<trace_api::Link> &links = {}) noexcept override;

void ForceFlushWithMicroseconds(uint64_t timeout) noexcept override;

Expand Down
6 changes: 6 additions & 0 deletions sdk/src/trace/span.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Span::Span(std::shared_ptr<Tracer> &&tracer,
nostd::string_view name,
const trace_api::KeyValueIterable &attributes,
const trace_api::StartSpanOptions &options,
const nostd::span<trace_api::Link> &links,
const trace_api::SpanContext &parent_span_context) noexcept
: tracer_{std::move(tracer)},
processor_{processor},
Expand Down Expand Up @@ -98,6 +99,11 @@ Span::Span(std::shared_ptr<Tracer> &&tracer,
return true;
});

for (auto const &link : links)
{
recordable_->AddLink(link.GetSpanContext(), link.GetAttributes());
}

recordable_->SetStartTime(NowOr(options.start_system_time));
start_steady_time = NowOr(options.start_steady_time);
processor_->OnStart(*recordable_);
Expand Down
1 change: 1 addition & 0 deletions sdk/src/trace/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Span final : public trace_api::Span
nostd::string_view name,
const trace_api::KeyValueIterable &attributes,
const trace_api::StartSpanOptions &options,
const nostd::span<trace_api::Link> &links,
const trace_api::SpanContext &parent_span_context) noexcept;

~Span() override;
Expand Down
5 changes: 3 additions & 2 deletions sdk/src/trace/tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ trace_api::SpanContext GetCurrentSpanContext()
nostd::shared_ptr<trace_api::Span> Tracer::StartSpan(
nostd::string_view name,
const trace_api::KeyValueIterable &attributes,
const trace_api::StartSpanOptions &options) noexcept
const trace_api::StartSpanOptions &options,
const nostd::span<trace_api::Link> &links) noexcept
{
// TODO: replace nullptr with parent context in span context
auto sampling_result =
Expand All @@ -65,7 +66,7 @@ nostd::shared_ptr<trace_api::Span> Tracer::StartSpan(
{
auto span = nostd::shared_ptr<trace_api::Span>{
new (std::nothrow) Span{this->shared_from_this(), processor_.load(), name, attributes,
options, GetCurrentSpanContext()}};
options, links, GetCurrentSpanContext()}};

// if the attributes is not nullptr, add attributes to the span.
if (sampling_result.attributes)
Expand Down
27 changes: 27 additions & 0 deletions sdk/test/trace/tracer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "opentelemetry/sdk/trace/samplers/parent_or_else.h"
#include "opentelemetry/sdk/trace/simple_processor.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include "opentelemetry/trace/link.h"

#include <gtest/gtest.h>

Expand All @@ -15,6 +16,8 @@ namespace nostd = opentelemetry::nostd;
namespace common = opentelemetry::common;
using opentelemetry::exporter::memory::InMemorySpanData;
using opentelemetry::exporter::memory::InMemorySpanExporter;
using opentelemetry::trace::KeyValueIterableView;
using opentelemetry::trace::Link;
using opentelemetry::trace::SpanContext;

/**
Expand Down Expand Up @@ -331,6 +334,30 @@ TEST(Tracer, SpanSetEvents)
ASSERT_EQ(1, span_data_events[2].GetAttributes().size());
}

TEST(Tracer, SpanSetLinks)
{
std::unique_ptr<InMemorySpanExporter> exporter(new InMemorySpanExporter());
std::shared_ptr<InMemorySpanData> span_data = exporter->GetData();
auto tracer = initTracer(std::move(exporter));

SpanContext sp(true, true);
using Map = std::map<nostd::string_view, int>;
Map m1 = {{"attr1", 123}, {"attr2", 456}};
KeyValueIterableView<Map> iterable{m1};
Link link(sp, iterable);
std::vector<Link> links = {link};
auto span = tracer->StartSpan("span 1", {}, {}, links);
span->End();
auto spans = span_data->GetSpans();
ASSERT_EQ(1, spans.size());
auto &span_data_links = spans.at(0)->GetLinks();
ASSERT_EQ(1, span_data_links.size());
auto link1 = span_data_links.at(0);
std::cout << nostd::get<int>(link1.GetAttributes().at("attr1"));
ASSERT_EQ(nostd::get<int>(link1.GetAttributes().at("attr1")), 123);
ASSERT_EQ(nostd::get<int>(link1.GetAttributes().at("attr2")), 456);
}

TEST(Tracer, TestAlwaysOnSampler)
{
std::unique_ptr<InMemorySpanExporter> exporter(new InMemorySpanExporter());
Expand Down