Skip to content

Commit

Permalink
Handle span events for jaeger exporter (#895)
Browse files Browse the repository at this point in the history
  • Loading branch information
lalitb authored Jul 8, 2021
1 parent 9b1725b commit 51b6b19
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class Recordable final : public sdk::trace::Recordable

thrift::Span *Span() noexcept { return span_.release(); }
std::vector<thrift::Tag> Tags() noexcept { return std::move(tags_); }
std::vector<thrift::Log> Logs() noexcept { return std::move(logs_); }
const std::string &ServiceName() const noexcept { return service_name_; }

void SetIdentity(const opentelemetry::trace::SpanContext &span_context,
Expand Down Expand Up @@ -88,18 +89,20 @@ class Recordable final : public sdk::trace::Recordable
&instrumentation_library) noexcept override;

private:
void AddTag(const std::string &key, const std::string &value);
void AddTag(const std::string &key, const char *value);
void AddTag(const std::string &key, bool value);
void AddTag(const std::string &key, int64_t value);
void AddTag(const std::string &key, double value);
void AddTag(const std::string &key, const std::string &value, std::vector<thrift::Tag> &tags);
void AddTag(const std::string &key, const char *value, std::vector<thrift::Tag> &tags);
void AddTag(const std::string &key, bool value, std::vector<thrift::Tag> &tags);
void AddTag(const std::string &key, int64_t value, std::vector<thrift::Tag> &tags);
void AddTag(const std::string &key, double value, std::vector<thrift::Tag> &tags);

void PopulateAttribute(nostd::string_view key,
const opentelemetry::common::AttributeValue &value);
const opentelemetry::common::AttributeValue &value,
std::vector<thrift::Tag> &tags);

private:
std::unique_ptr<thrift::Span> span_;
std::vector<thrift::Tag> tags_;
std::vector<thrift::Log> logs_;
std::string service_name_;
};

Expand Down
65 changes: 40 additions & 25 deletions exporters/jaeger/src/recordable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,29 @@ using namespace opentelemetry::sdk::resource;

Recordable::Recordable() : span_{new thrift::Span} {}

void Recordable::PopulateAttribute(nostd::string_view key, const common::AttributeValue &value)
void Recordable::PopulateAttribute(nostd::string_view key,
const common::AttributeValue &value,
std::vector<thrift::Tag> &tags)
{
if (nostd::holds_alternative<int64_t>(value))
{
AddTag(std::string{key}, nostd::get<int64_t>(value));
AddTag(std::string{key}, nostd::get<int64_t>(value), tags);
}
else if (nostd::holds_alternative<bool>(value))
{
AddTag(std::string{key}, nostd::get<bool>(value));
AddTag(std::string{key}, nostd::get<bool>(value), tags);
}
else if (nostd::holds_alternative<double>(value))
{
AddTag(std::string{key}, nostd::get<double>(value));
AddTag(std::string{key}, nostd::get<double>(value), tags);
}
else if (nostd::holds_alternative<const char *>(value))
{
AddTag(std::string{key}, std::string{nostd::get<const char *>(value)});
AddTag(std::string{key}, std::string{nostd::get<const char *>(value)}, tags);
}
else if (nostd::holds_alternative<nostd::string_view>(value))
{
AddTag(std::string{key}, std::string{nostd::get<nostd::string_view>(value)});
AddTag(std::string{key}, std::string{nostd::get<nostd::string_view>(value)}, tags);
}
// TODO: extend other AttributeType to the types supported by Jaeger.
}
Expand Down Expand Up @@ -67,22 +69,33 @@ void Recordable::SetIdentity(const trace::SpanContext &span_context,

void Recordable::SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept
{
PopulateAttribute(key, value);
PopulateAttribute(key, value, tags_);
}

void Recordable::AddEvent(nostd::string_view name,
common::SystemTimestamp timestamp,
const common::KeyValueIterable &attributes) noexcept
{
// TODO: convert event to Jaeger Log
std::vector<thrift::Tag> tags;
PopulateAttribute("event", name.data(), tags);

attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept {
PopulateAttribute(key, value, tags);
return true;
});
thrift::Log log;
log.__set_fields(tags);
log.__set_timestamp(
std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count());
logs_.push_back(log);
}

void Recordable::SetInstrumentationLibrary(
const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary
&instrumentation_library) noexcept
{
AddTag("otel.library.name", instrumentation_library.GetName());
AddTag("otel.library.version", instrumentation_library.GetVersion());
AddTag("otel.library.name", instrumentation_library.GetName(), tags_);
AddTag("otel.library.version", instrumentation_library.GetVersion(), tags_);
}

void Recordable::AddLink(const trace::SpanContext &span_context,
Expand All @@ -100,15 +113,15 @@ void Recordable::SetStatus(trace::StatusCode code, nostd::string_view descriptio

if (code == trace::StatusCode::kOk)
{
AddTag("otel.status_code", "OK");
AddTag("otel.status_code", "OK", tags_);
}
else if (code == trace::StatusCode::kError)
{
AddTag("otel.status_code", "ERROR");
AddTag("error", true);
AddTag("otel.status_code", "ERROR", tags_);
AddTag("error", true, tags_);
}

AddTag("otel.status_description", std::string{description});
AddTag("otel.status_description", std::string{description}, tags_);
}

void Recordable::SetName(nostd::string_view name) noexcept
Expand Down Expand Up @@ -166,57 +179,59 @@ void Recordable::SetSpanKind(trace::SpanKind span_kind) noexcept

if (span_kind_str != nullptr)
{
AddTag("span.kind", span_kind_str);
AddTag("span.kind", span_kind_str, tags_);
}
}

void Recordable::AddTag(const std::string &key, const std::string &value)
void Recordable::AddTag(const std::string &key,
const std::string &value,
std::vector<thrift::Tag> &tags)
{
thrift::Tag tag;

tag.__set_key(key);
tag.__set_vType(thrift::TagType::STRING);
tag.__set_vStr(value);

tags_.push_back(tag);
tags.push_back(tag);
}

void Recordable::AddTag(const std::string &key, const char *value)
void Recordable::AddTag(const std::string &key, const char *value, std::vector<thrift::Tag> &tags)
{
AddTag(key, std::string{value});
AddTag(key, std::string{value}, tags);
}

void Recordable::AddTag(const std::string &key, bool value)
void Recordable::AddTag(const std::string &key, bool value, std::vector<thrift::Tag> &tags)
{
thrift::Tag tag;

tag.__set_key(key);
tag.__set_vType(thrift::TagType::BOOL);
tag.__set_vBool(value);

tags_.push_back(tag);
tags.push_back(tag);
}

void Recordable::AddTag(const std::string &key, int64_t value)
void Recordable::AddTag(const std::string &key, int64_t value, std::vector<thrift::Tag> &tags)
{
thrift::Tag tag;

tag.__set_key(key);
tag.__set_vType(thrift::TagType::LONG);
tag.__set_vLong(value);

tags_.push_back(tag);
tags.push_back(tag);
}

void Recordable::AddTag(const std::string &key, double value)
void Recordable::AddTag(const std::string &key, double value, std::vector<thrift::Tag> &tags)
{
thrift::Tag tag;

tag.__set_key(key);
tag.__set_vType(thrift::TagType::DOUBLE);
tag.__set_vDouble(value);

tags_.push_back(tag);
tags.push_back(tag);
}

} // namespace jaeger
Expand Down
1 change: 1 addition & 0 deletions exporters/jaeger/src/thrift_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ int ThriftSender::Append(std::unique_ptr<Recordable> &&span) noexcept

thrift::Span &jaeger_span = *span->Span();
jaeger_span.__set_tags(span->Tags());
jaeger_span.__set_logs(span->Logs());

const uint32_t span_size = CalcSizeOfSerializedThrift(jaeger_span);
if (span_size > max_span_bytes)
Expand Down
34 changes: 34 additions & 0 deletions exporters/jaeger/test/jaeger_recordable_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,40 @@ TEST(JaegerSpanRecordable, SetStatus)
EXPECT_EQ(tags[2].vStr, error_description);
}

TEST(JaegerSpanRecordable, AddEvent)
{
opentelemetry::exporter::jaeger::Recordable rec;

nostd::string_view name = "Test Event";

std::chrono::system_clock::time_point event_time = std::chrono::system_clock::now();
opentelemetry::common::SystemTimestamp event_timestamp(event_time);
uint64_t epoch_us =
std::chrono::duration_cast<std::chrono::microseconds>(event_time.time_since_epoch()).count();

const int kNumAttributes = 3;
std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3"};
int64_t values[kNumAttributes] = {4, 7, 23};
std::map<std::string, int64_t> attributes = {
{keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}};

rec.AddEvent(
"Test Event", event_timestamp,
opentelemetry::common::KeyValueIterableView<std::map<std::string, int64_t>>(attributes));
thrift::Log log = rec.Logs().at(0);
EXPECT_EQ(log.timestamp, epoch_us);
auto tags = log.fields;
size_t index = 0;
EXPECT_EQ(tags[index].key, "event");
EXPECT_EQ(tags[index++].vStr, "Test Event");
while (index <= kNumAttributes)
{
EXPECT_EQ(tags[index].key, keys[index - 1]);
EXPECT_EQ(tags[index].vLong, values[index - 1]);
index++;
}
}

TEST(JaegerSpanRecordable, SetInstrumentationLibrary)
{
opentelemetry::exporter::jaeger::Recordable rec;
Expand Down

0 comments on commit 51b6b19

Please sign in to comment.