Skip to content

Commit

Permalink
[API] Add a new AddLink() operation to Span (#2380)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcalff authored Oct 27, 2023
1 parent d3a873a commit 17da6d8
Show file tree
Hide file tree
Showing 11 changed files with 623 additions and 3 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Increment the:
[#2371](https://github.com/open-telemetry/opentelemetry-cpp/pull/2371)
* [BUILD] enum CanonicalCode names too generic... conflict with old C defines
[#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385)
* [API] Add a new AddLink() operation to Span
[#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380)

Important changes:

Expand All @@ -34,6 +36,15 @@ Important changes:
* When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default)
the `ABI` is unchanged, and the fix is not available.

* [API] Add a new AddLink() operation to Span
[#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380)
* New `API` Span::AddLink() adds a single link to a span.
* New `API` Span::AddLinks() adds multiple links to a span.
* Because this is an `ABI` breaking change, the fix is only available
with the `CMake` option `WITH_ABI_VERSION_2=ON`.
* When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default)
the `ABI` is unchanged, and the fix is not available.

* [BUILD] Make WITH_OTLP_HTTP_SSL_PREVIEW mainstream
[#2378](https://github.com/open-telemetry/opentelemetry-cpp/pull/2378)
* The experimental `CMake` option `WITH_OTLP_HTTP_SSL_PREVIEW`
Expand Down
14 changes: 14 additions & 0 deletions api/include/opentelemetry/plugin/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "opentelemetry/common/key_value_iterable.h"
#include "opentelemetry/plugin/detail/tracer_handle.h"
#include "opentelemetry/trace/span_context_kv_iterable.h"
#include "opentelemetry/trace/tracer.h"
#include "opentelemetry/version.h"

Expand Down Expand Up @@ -49,6 +50,19 @@ class Span final : public trace::Span
span_->AddEvent(name, timestamp, attributes);
}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void AddLink(const trace::SpanContext &target,
const common::KeyValueIterable &attrs) noexcept override
{
span_->AddLink(target, attrs);
}

void AddLinks(const trace::SpanContextKeyValueIterable &links) noexcept override
{
span_->AddLinks(links);
}
#endif

void SetStatus(trace::StatusCode code, nostd::string_view description) noexcept override
{
span_->SetStatus(code, description);
Expand Down
8 changes: 8 additions & 0 deletions api/include/opentelemetry/trace/default_span.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ class DefaultSpan : public Span
const common::KeyValueIterable & /* attributes */) noexcept override
{}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void AddLink(const SpanContext & /* target */,
const common::KeyValueIterable & /* attrs */) noexcept override
{}

void AddLinks(const SpanContextKeyValueIterable & /* links */) noexcept override {}
#endif

void SetStatus(StatusCode /* status */, nostd::string_view /* description */) noexcept override {}

void UpdateName(nostd::string_view /* name */) noexcept override {}
Expand Down
9 changes: 9 additions & 0 deletions api/include/opentelemetry/trace/noop.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/trace/span.h"
#include "opentelemetry/trace/span_context.h"
#include "opentelemetry/trace/span_context_kv_iterable.h"
#include "opentelemetry/trace/tracer.h"
#include "opentelemetry/trace/tracer_provider.h"
#include "opentelemetry/version.h"
Expand Down Expand Up @@ -58,6 +59,14 @@ class OPENTELEMETRY_EXPORT NoopSpan final : public Span
const common::KeyValueIterable & /*attributes*/) noexcept override
{}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void AddLink(const SpanContext & /* target */,
const common::KeyValueIterable & /* attrs */) noexcept override
{}

void AddLinks(const SpanContextKeyValueIterable & /* links */) noexcept override {}
#endif

void SetStatus(StatusCode /*code*/, nostd::string_view /*description*/) noexcept override {}

void UpdateName(nostd::string_view /*name*/) noexcept override {}
Expand Down
138 changes: 135 additions & 3 deletions api/include/opentelemetry/trace/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/trace/span_context.h"
#include "opentelemetry/trace/span_context_kv_iterable.h"
#include "opentelemetry/trace/span_context_kv_iterable_view.h"
#include "opentelemetry/trace/span_metadata.h"

#include "opentelemetry/version.h"
Expand All @@ -23,6 +25,31 @@ class Tracer;

/**
* A Span represents a single operation within a Trace.
*
* Span attributes can be provided:
* - at span creation time, using Tracer::StartSpan(),
* - during the span lifetime, using Span::SetAttribute()
*
* Please note that head samplers,
* in the SDK (@ref opentelemetry::sdk::trace::Sampler),
* can only make sampling decisions based on data known
* at span creation time.
*
* When attributes are known early, adding attributes
* with @ref opentelemetry::trace::Tracer::StartSpan() is preferable.
*
* Attributes added or changed with Span::SetAttribute()
* can not change a sampler decision.
*
* Likewise, links can be provided:
* - at span creation time, using Tracer::StartSpan(),
* - during the span lifetime, using Span::AddLink() or Span::AddLinks().
*
* When links are known early, adding links
* with @ref opentelemetry::trace::Tracer::StartSpan() is preferable.
*
* Links added with Span::AddLink() or Span::AddLinks()
* can not change a sampler decision.
*/
class Span
{
Expand All @@ -40,9 +67,14 @@ class Span
Span &operator=(const Span &) = delete;
Span &operator=(Span &&) = delete;

// Sets an attribute on the Span. If the Span previously contained a mapping
// for
// the key, the old value is replaced.
/**
* Sets an attribute on the Span (ABI).
*
* If the Span previously contained a mapping for the key,
* the old value is replaced.
*
* See comments about sampling in @ref opentelemetry::trace::Span
*/
virtual void SetAttribute(nostd::string_view key,
const common::AttributeValue &value) noexcept = 0;

Expand Down Expand Up @@ -98,6 +130,106 @@ class Span
attributes.begin(), attributes.end()});
}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2

/**
* Add link (ABI).
*
* See comments about sampling in @ref opentelemetry::trace::Span
*
* @since ABI_VERSION 2
*/
virtual void AddLink(const SpanContext &target,
const common::KeyValueIterable &attrs) noexcept = 0;

/**
* Add links (ABI).
*
* See comments about sampling in @ref opentelemetry::trace::Span
*
* @since ABI_VERSION 2
*/
virtual void AddLinks(const SpanContextKeyValueIterable &links) noexcept = 0;

/**
* Add link (API helper).
*
* See comments about sampling in @ref opentelemetry::trace::Span
*
* @since ABI_VERSION 2
*/
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void AddLink(const SpanContext &target, const U &attrs)
{
common::KeyValueIterableView<U> view(attrs);
this->AddLink(target, view);
}

/**
* Add link (API helper).
*
* See comments about sampling in @ref opentelemetry::trace::Span
*
* @since ABI_VERSION 2
*/
void AddLink(const SpanContext &target,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attrs)
{
/* Build a container from std::initializer_list. */
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>> container{
attrs.begin(), attrs.end()};

/* Build a view on the container. */
common::KeyValueIterableView<
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>>
view(container);

return this->AddLink(target, view);
}

/**
* Add links (API helper).
*
* See comments about sampling in @ref opentelemetry::trace::Span
*
* @since ABI_VERSION 2
*/
template <class U, nostd::enable_if_t<detail::is_span_context_kv_iterable<U>::value> * = nullptr>
void AddLinks(const U &links)
{
SpanContextKeyValueIterableView<U> view(links);
this->AddLinks(view);
}

/**
* Add links (API helper).
*
* See comments about sampling in @ref opentelemetry::trace::Span
*
* @since ABI_VERSION 2
*/
void AddLinks(
std::initializer_list<
std::pair<SpanContext,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>>>
links)
{
/* Build a container from std::initializer_list. */
nostd::span<const std::pair<
SpanContext, std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>>>
container{links.begin(), links.end()};

/* Build a view on the container. */
SpanContextKeyValueIterableView<nostd::span<const std::pair<
SpanContext, std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>>>>
view(container);

return this->AddLinks(view);
}

#endif /* OPENTELEMETRY_ABI_VERSION_NO */

// Sets the status of the span. The default status is Unset. Only the value of
// the last call will be
// recorded, and implementations are free to ignore previous calls.
Expand Down
1 change: 1 addition & 0 deletions api/include/opentelemetry/trace/span_context_kv_iterable.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/key_value_iterable_view.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/trace/span_context.h"
#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
Expand Down
15 changes: 15 additions & 0 deletions api/test/trace/noop_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ TEST(NoopTest, UseNoopTracers)
s1->GetContext();
}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
TEST(NoopTest, UseNoopTracersAbiv2)
{
std::shared_ptr<trace_api::Tracer> tracer{new trace_api::NoopTracer{}};
auto s1 = tracer->StartSpan("abc");

EXPECT_EQ(s1->IsRecording(), false);

trace_api::SpanContext target(false, false);
s1->AddLink(target, {{"noop1", 1}});

s1->AddLinks({{trace_api::SpanContext(false, false), {{"noop2", 2}}}});
}
#endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */

TEST(NoopTest, StartSpan)
{
std::shared_ptr<trace_api::Tracer> tracer{new trace_api::NoopTracer{}};
Expand Down
8 changes: 8 additions & 0 deletions examples/plugin/plugin/tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ class Span final : public trace::Span
const common::KeyValueIterable & /*attributes*/) noexcept override
{}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void AddLink(const trace::SpanContext & /* target */,
const common::KeyValueIterable & /* attrs */) noexcept override
{}

void AddLinks(const trace::SpanContextKeyValueIterable & /* links */) noexcept override {}
#endif

void SetStatus(trace::StatusCode /*code*/, nostd::string_view /*description*/) noexcept override
{}

Expand Down
29 changes: 29 additions & 0 deletions sdk/src/trace/span.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,35 @@ void Span::AddEvent(nostd::string_view name,
recordable_->AddEvent(name, timestamp, attributes);
}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void Span::AddLink(const opentelemetry::trace::SpanContext &target,
const opentelemetry::common::KeyValueIterable &attrs) noexcept
{
std::lock_guard<std::mutex> lock_guard{mu_};
if (recordable_ == nullptr)
{
return;
}

recordable_->AddLink(target, attrs);
}

void Span::AddLinks(const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept
{
std::lock_guard<std::mutex> lock_guard{mu_};
if (recordable_ == nullptr)
{
return;
}

links.ForEachKeyValue([&](opentelemetry::trace::SpanContext span_context,
const common::KeyValueIterable &attributes) {
recordable_->AddLink(span_context, attributes);
return true;
});
}
#endif

void Span::SetStatus(opentelemetry::trace::StatusCode code, nostd::string_view description) noexcept
{
std::lock_guard<std::mutex> lock_guard{mu_};
Expand Down
7 changes: 7 additions & 0 deletions sdk/src/trace/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ class Span final : public opentelemetry::trace::Span
opentelemetry::common::SystemTimestamp timestamp,
const opentelemetry::common::KeyValueIterable &attributes) noexcept override;

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void AddLink(const opentelemetry::trace::SpanContext &target,
const opentelemetry::common::KeyValueIterable &attrs) noexcept override;

void AddLinks(const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept override;
#endif

void SetStatus(opentelemetry::trace::StatusCode code,
nostd::string_view description) noexcept override;

Expand Down
Loading

2 comments on commit 17da6d8

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'OpenTelemetry-cpp sdk Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: 17da6d8 Previous: d3a873a Ratio
BM_BaselineBuffer/2 9823343.753814697 ns/iter 1114939.9280548096 ns/iter 8.81

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'OpenTelemetry-cpp api Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: 17da6d8 Previous: d3a873a Ratio
BM_ExtractBaggageHavingTenEntries 3.714044849569614 ns/iter 1.6210075698342716 ns/iter 2.29
BM_ExtractBaggageWith180Entries 4.136306589702201 ns/iter 1.6178948645384408 ns/iter 2.56
BM_SpinLockThrashing/2/process_time/real_time 0.6337006067492298 ms/iter 0.24845172430722767 ms/iter 2.55
BM_ProcYieldSpinLockThrashing/1/process_time/real_time 0.29659424399921164 ms/iter 0.11324766582569389 ms/iter 2.62
BM_ProcYieldSpinLockThrashing/2/process_time/real_time 0.7278108596801758 ms/iter 0.24030959236680197 ms/iter 3.03

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.