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

Implement Span::Log() using annotations #18

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
28 changes: 24 additions & 4 deletions zipkin_opentracing/src/opentracing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ static const OtSpanContext *findSpanContext(
return nullptr;
}

static void appendAnnotations(Span& span, const std::vector<ot::LogRecord>& log_records, Endpoint endpoint) {
for (const auto &lr : log_records) {
const auto timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
lr.timestamp.time_since_epoch()).count();
Annotation annotation = toAnnotation({ lr.fields.begin(), lr.fields.end() });
annotation.setTimestamp(timestamp);
annotation.setEndpoint(endpoint);
span.addAnnotation(annotation);
}
}

class OtSpan : public ot::Span {
public:
OtSpan(std::shared_ptr<const ot::Tracer> &&tracer_owner, SpanPtr &&span_owner,
Expand Down Expand Up @@ -186,7 +197,7 @@ class OtSpan : public ot::Span {
.count());
span_->setDuration(duration_microsecs);

// Set tags and finish
// Set tags, log records and finish
std::lock_guard<std::mutex> lock{mutex_};

// Set appropriate CS/SR/SS/CR annotations if span.kind is set.
Expand Down Expand Up @@ -218,6 +229,12 @@ class OtSpan : public ot::Span {
for (const auto &tag : tags_) {
span_->addBinaryAnnotation(toBinaryAnnotation(tag.first, tag.second));
}

std::vector<ot::LogRecord> log_records;
log_records.swap(log_records_);
appendAnnotations(*span_, log_records, endpoint_);
appendAnnotations(*span_, options.log_records, endpoint_);

span_->finish();
} catch (const std::bad_alloc &) {
// Do nothing if memory allocation fails.
Expand Down Expand Up @@ -246,8 +263,10 @@ class OtSpan : public ot::Span {
return span_context_.baggageItem(restricted_key);
}

void Log(std::initializer_list<std::pair<string_view, Value>>
fields) noexcept override {}
void Log(std::initializer_list<std::pair<string_view, Value>> fields) noexcept override {
std::lock_guard<std::mutex> lock_guard{mutex_};
log_records_.push_back({ SystemClock::now(), { fields.begin(), fields.end() } });
}
Copy link
Owner

Choose a reason for hiding this comment

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

This can potentially throw std::bad_alloc, so you need a try/catch block here like what's done in SetTag.


const ot::SpanContext &context() const noexcept override {
return span_context_;
Expand All @@ -261,10 +280,11 @@ class OtSpan : public ot::Span {
OtSpanContext span_context_;
SteadyTime start_steady_timestamp_;

// Mutex protects tags_ and span_
// Mutex protects tags_, log_records_ and span_
std::atomic<bool> is_finished_{false};
std::mutex mutex_;
std::unordered_map<std::string, Value> tags_;
std::vector<ot::LogRecord> log_records_;
SpanPtr span_;
};

Expand Down
56 changes: 42 additions & 14 deletions zipkin_opentracing/src/utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,48 +78,76 @@ static std::string toJson(const Value &value) {
}

namespace {
struct ValueVisitor {
BinaryAnnotation &annotation;

struct SetValueVisitor {
BinaryAnnotation& annotation;
const Value &original_value;

// natively handled types

void operator()(bool value) const {
annotation.setValue(std::to_string(value));
annotation.setValue(value);
}

void operator()(double value) const {
annotation.setValue(std::to_string(value));
annotation.setValue(value);
}

void operator()(int64_t value) const {
annotation.setValue(std::to_string(value));
annotation.setValue(value);
}

void operator()(const std::string &s) const {
annotation.setValue(s);
}

// overrides

void operator()(uint64_t value) const {
// There's no uint64_t value type so cast to an int64_t.
annotation.setValue(std::to_string(value));
int64_t cast = value;
(*this)(cast);
}

void operator()(const std::string &s) const { annotation.setValue(s); }

void operator()(std::nullptr_t) const { annotation.setValue("0"); }
void operator()(std::nullptr_t) const {
(*this)("0");
}

void operator()(const char *s) const { annotation.setValue(std::string{s}); }
void operator()(const char *s) const {
(*this)(std::string(s));
}

void operator()(const Values & /*unused*/) const {
annotation.setValue(toJson(original_value));
(*this)(toJson(original_value));
}

void operator()(const Dictionary & /*unused*/) const {
annotation.setValue(toJson(original_value));
(*this)(toJson(original_value));
}
};

} // anonymous namespace

BinaryAnnotation toBinaryAnnotation(string_view key, const Value &value) {
BinaryAnnotation annotation;
annotation.setKey(key);
ValueVisitor value_visitor{annotation, value};
apply_visitor(value_visitor, value);
SetValueVisitor visitor{annotation, value};
apply_visitor(visitor, value);
return annotation;
}

Annotation toAnnotation(const std::vector<std::pair<string_view, Value>>& fields) {
rapidjson::StringBuffer buffer;
JsonWriter writer(buffer);
writer.StartObject();
for (auto & field : fields) {
writer.Key(field.first.data());
toJson(writer, field.second);
}
writer.EndObject();
Annotation annotation;
annotation.setValue(buffer.GetString());
return annotation;
}

} // namespace zipkin
4 changes: 4 additions & 0 deletions zipkin_opentracing/src/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
#include <zipkin/zipkin_core_types.h>

namespace zipkin {

BinaryAnnotation toBinaryAnnotation(opentracing::string_view key,
const opentracing::Value &value);

Annotation toAnnotation(const std::vector<std::pair<opentracing::string_view, opentracing::Value>>& fields);

} // namespace zipkin