Skip to content

Commit

Permalink
Cleanup and more unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
chusitoo committed Jan 4, 2023
1 parent 22949e2 commit f62eb78
Show file tree
Hide file tree
Showing 9 changed files with 505 additions and 282 deletions.
96 changes: 96 additions & 0 deletions opentracing-shim/include/propagation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "opentelemetry/baggage/baggage.h"
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/context/propagation/text_map_propagator.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentracing/propagation.h"
#include "opentracing/value.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace opentracingshim
{

template<typename T, nostd::enable_if_t<std::is_base_of<opentracing::TextMapWriter, T>::value, bool> = true>
class CarrierWriterShim : public opentelemetry::context::propagation::TextMapCarrier
{
public:
CarrierWriterShim(const T& writer) : writer_(writer) {}

// returns the value associated with the passed key.
virtual nostd::string_view Get(nostd::string_view key) const noexcept override
{
return "";
}

// stores the key-value pair.
virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
{
writer_.Set(key.data(), value.data());
}

private:
const T& writer_;
};

template<typename T, nostd::enable_if_t<std::is_base_of<opentracing::TextMapReader, T>::value, bool> = true>
class CarrierReaderShim : public opentelemetry::context::propagation::TextMapCarrier
{
public:
CarrierReaderShim(const T& reader) : reader_(reader) {}

// returns the value associated with the passed key.
virtual nostd::string_view Get(nostd::string_view key) const noexcept override
{
nostd::string_view value;

// First try carrier.LookupKey since that can potentially be the fastest approach.
if (auto result = reader_.LookupKey(key.data()))
{
value = result.value().data();
}
else // Fall back to iterating through all of the keys.
{
reader_.ForeachKey([key, &value]
(opentracing::string_view k, opentracing::string_view v) -> opentracing::expected<void> {
if (k == key.data())
{
value = v.data();
// Found key, so bail out of the loop with a success error code.
return opentracing::make_unexpected(std::error_code{});
}
return opentracing::make_expected();
});
}

return value;
}

// stores the key-value pair.
virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
{
// Not required for Opentracing reader
}

// list of all the keys in the carrier.
virtual bool Keys(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override
{
return reader_.ForeachKey([&callback]
(opentracing::string_view key, opentracing::string_view) -> opentracing::expected<void> {
return callback(key.data())
? opentracing::make_expected()
: opentracing::make_unexpected(std::error_code{});
}).has_value();
}

private:
const T& reader_;
};

} // namespace opentracingshim
OPENTELEMETRY_END_NAMESPACE
174 changes: 108 additions & 66 deletions opentracing-shim/include/shim_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@

#pragma once

#include <opentelemetry/baggage/baggage.h>
#include <opentelemetry/common/attribute_value.h>
#include <opentelemetry/context/propagation/text_map_propagator.h>
#include <opentelemetry/nostd/type_traits.h>
#include <opentracing/propagation.h>
#include <opentracing/value.h>
#include "span_context_shim.h"

#include "opentelemetry/baggage/baggage.h"
#include "opentelemetry/baggage/baggage_context.h"
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/context/propagation/text_map_propagator.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/trace/semantic_conventions.h"
#include "opentelemetry/trace/tracer.h"
#include "opentracing/propagation.h"
#include "opentracing/tracer.h"
#include "opentracing/value.h"

#include <iostream>

OPENTELEMETRY_BEGIN_NAMESPACE
namespace opentracingshim::utils
Expand Down Expand Up @@ -56,92 +64,126 @@ static inline std::string stringFromValue(const opentracing::Value& value)
return opentracing::Value::visit(value, StringMapper);
}

template<typename T, nostd::enable_if_t<std::is_base_of<opentracing::TextMapWriter, T>::value, bool> = true>
class CarrierWriterShim : public opentelemetry::context::propagation::TextMapCarrier
static inline bool isBaggageEmpty(const nostd::shared_ptr<opentelemetry::baggage::Baggage>& baggage)
{
public:
CarrierWriterShim(const T& writer) : writer_(writer) {}

// returns the value associated with the passed key.
virtual nostd::string_view Get(nostd::string_view key) const noexcept override
if (baggage)
{
return "";
return baggage->GetAllEntries([](nostd::string_view, nostd::string_view){
return false;
});
}

// stores the key-value pair.
virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
return true;
}

static opentelemetry::trace::StartSpanOptions makeOptionsShim(const opentracing::StartSpanOptions& options) noexcept
{
using opentracing::SpanReferenceType;
// If an explicit start timestamp is specified, a conversion MUST
// be done to match the OpenTracing and OpenTelemetry units.
opentelemetry::trace::StartSpanOptions options_shim;
options_shim.start_system_time = opentelemetry::common::SystemTimestamp{options.start_system_timestamp};
options_shim.start_steady_time = opentelemetry::common::SteadyTimestamp{options.start_steady_timestamp};

const auto& refs = options.references;
// If a list of Span references is specified...
if (!refs.empty())
{
writer_.Set(key.data(), value.data());
auto first_child_of = std::find_if(refs.cbegin(), refs.cend(),
[](const std::pair<SpanReferenceType, const opentracing::SpanContext*>& entry){
return entry.first == SpanReferenceType::ChildOfRef;
});
// The first SpanContext with Child Of type in the entire list is used as parent,
// else the first SpanContext is used as parent
auto context = (first_child_of != refs.cend()) ? first_child_of->second : refs.cbegin()->second;

if (auto context_shim = dynamic_cast<const SpanContextShim*>(context))
{
options_shim.parent = context_shim->context();
}
}

private:
const T& writer_;
};
return options_shim;
}

template<typename T, nostd::enable_if_t<std::is_base_of<opentracing::TextMapReader, T>::value, bool> = true>
class CarrierReaderShim : public opentelemetry::context::propagation::TextMapCarrier
{
public:
CarrierReaderShim(const T& reader) : reader_(reader) {}
using RefsList = std::vector<std::pair<nostd::string_view, common::AttributeValue>>;
using LinksList = std::vector<std::pair<opentelemetry::trace::SpanContext, RefsList>>;

// returns the value associated with the passed key.
virtual nostd::string_view Get(nostd::string_view key) const noexcept override
static LinksList makeReferenceLinks(const opentracing::StartSpanOptions& options) noexcept
{
using opentracing::SpanReferenceType;
using namespace opentelemetry::trace::SemanticConventions;

LinksList links;
links.reserve(options.references.size());
// All values in the list MUST be added as Links with the reference type value
// as a Link attribute, i.e. opentracing.ref_type set to follows_from or child_of
for (const auto& entry : options.references)
{
nostd::string_view value;
auto context_shim = dynamic_cast<const SpanContextShim*>(entry.second);
nostd::string_view span_kind;

// First try carrier.LookupKey since that can potentially be the fastest approach.
if (auto result = reader_.LookupKey(key.data()))
if (entry.first == SpanReferenceType::ChildOfRef)
{
value = result.value().data();
span_kind = OpentracingRefTypeValues::kChildOf;
}
else // Fall back to iterating through all of the keys.
else if (entry.first == SpanReferenceType::FollowsFromRef)
{
reader_.ForeachKey([key, &value]
(opentracing::string_view k, opentracing::string_view v) -> opentracing::expected<void> {
if (k == key.data())
{
value = v.data();
// Found key, so bail out of the loop with a success error code.
return opentracing::make_unexpected(std::error_code{});
}
return opentracing::make_expected();
});
span_kind = OpentracingRefTypeValues::kFollowsFrom;
}

return value;
if (context_shim && !span_kind.empty())
{
links.emplace_back(std::piecewise_construct,
std::forward_as_tuple(context_shim->context()),
std::forward_as_tuple(std::forward<RefsList>({{ kOpentracingRefType, span_kind }})));
}
}

// stores the key-value pair.
virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
{
// Not required for Opentracing reader
}
return links;
}

// list of all the keys in the carrier.
virtual bool Keys(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override
static nostd::shared_ptr<opentelemetry::baggage::Baggage> makeBaggage(const opentracing::StartSpanOptions& options) noexcept
{
using namespace opentelemetry::baggage;

std::unordered_map<std::string, std::string> baggage_items;
// If a list of Span references is specified...
for (const auto& entry : options.references)
{
return reader_.ForeachKey([&callback]
(opentracing::string_view key, opentracing::string_view) -> opentracing::expected<void> {
return callback(key.data())
? opentracing::make_expected()
: opentracing::make_unexpected(std::error_code{});
}).has_value();
if (auto context_shim = dynamic_cast<const SpanContextShim*>(entry.second))
{
// The union of their Baggage values MUST be used as the initial Baggage of the newly created Span.
context_shim->ForeachBaggageItem([&baggage_items](const std::string& key, const std::string& value){
// It is unspecified which Baggage value is used in the case of repeated keys.
if (baggage_items.find(key) == baggage_items.end())
{
baggage_items.emplace(key, value); // Here, only insert if key not already present
}
return true;
});
}
}
// If no such list of references is specified, the current Baggage
// MUST be used as the initial value of the newly created Span.
return baggage_items.empty()
? GetBaggage(opentelemetry::context::RuntimeContext::GetCurrent())
: nostd::shared_ptr<Baggage>(new Baggage(baggage_items));
}

private:
const T& reader_;
};

static inline bool isBaggageEmpty(const nostd::shared_ptr<opentelemetry::baggage::Baggage>& baggage)
static std::vector<std::pair<std::string, common::AttributeValue>> makeTags(const opentracing::StartSpanOptions& options) noexcept
{
if (baggage)
std::vector<std::pair<std::string, common::AttributeValue>> tags;
tags.reserve(options.tags.size());

// If an initial set of tags is specified, the values MUST
// be set at the creation time of the OpenTelemetry Span.
for (const auto& entry : options.tags)
{
return baggage->GetAllEntries([](nostd::string_view, nostd::string_view){
return false;
});
tags.emplace_back(entry.first, utils::attributeFromValue(entry.second));
}

return true;
return tags;
}

} // namespace opentracingshim::utils
Expand Down
2 changes: 1 addition & 1 deletion opentracing-shim/src/span_shim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "opentelemetry/trace/semantic_conventions.h"
#include "opentelemetry/trace/span_metadata.h"
#include <opentracing/ext/tags.h>
#include "opentracing/ext/tags.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace opentracingshim
Expand Down
Loading

0 comments on commit f62eb78

Please sign in to comment.