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

[API] Add a new AddLink() operation to Span #2380

Merged
merged 11 commits into from
Oct 27, 2023
Merged
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`.
marcalff marked this conversation as resolved.
Show resolved Hide resolved
* 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
marcalff marked this conversation as resolved.
Show resolved Hide resolved

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
*/
marcalff marked this conversation as resolved.
Show resolved Hide resolved
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
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 @@ -45,6 +45,13 @@ class Span final : public opentelemetry::trace::Span
void SetStatus(opentelemetry::trace::StatusCode code,
nostd::string_view description) noexcept override;

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void AddLink(const opentelemetry::trace::SpanContext &target,
marcalff marked this conversation as resolved.
Show resolved Hide resolved
const opentelemetry::common::KeyValueIterable &attrs) noexcept override;

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

void UpdateName(nostd::string_view name) noexcept override;

void End(const opentelemetry::trace::EndSpanOptions &options = {}) noexcept override;
Expand Down
Loading