Skip to content

Commit

Permalink
Span timing
Browse files Browse the repository at this point in the history
  • Loading branch information
Johannes Tax committed Jun 6, 2020
1 parent 273a0ae commit 9db466a
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 19 deletions.
10 changes: 10 additions & 0 deletions api/include/opentelemetry/core/timestamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ class SystemTimestamp
return std::chrono::nanoseconds{nanos_since_epoch_};
}

bool operator==(const SystemTimestamp &other) const noexcept
{
return nanos_since_epoch_ == other.nanos_since_epoch_;
}

private:
int64_t nanos_since_epoch_;
};
Expand Down Expand Up @@ -79,6 +84,11 @@ class SteadyTimestamp
return std::chrono::nanoseconds{nanos_since_epoch_};
}

bool operator==(const SteadyTimestamp &other) const noexcept
{
return nanos_since_epoch_ == other.nanos_since_epoch_;
}

private:
int64_t nanos_since_epoch_;
};
Expand Down
2 changes: 1 addition & 1 deletion api/include/opentelemetry/plugin/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Span final : public trace::Span

void UpdateName(nostd::string_view name) noexcept override { span_->UpdateName(name); }

void End() noexcept override { span_->End(); }
void End(const trace::EndSpanOptions &options = {}) noexcept override { span_->End(options); }

bool IsRecording() const noexcept override { return span_->IsRecording(); }

Expand Down
2 changes: 1 addition & 1 deletion api/include/opentelemetry/trace/noop.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class NoopSpan final : public Span

void UpdateName(nostd::string_view /*name*/) noexcept override {}

void End() noexcept override {}
void End(const EndSpanOptions & /*options*/) noexcept override {}

bool IsRecording() const noexcept override { return false; }

Expand Down
10 changes: 6 additions & 4 deletions api/include/opentelemetry/trace/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ struct StartSpanOptions
SpanKind kind = SpanKind::kInternal;
};

struct EndSpanOptions
{
core::SteadyTimestamp end_steady_time;
};

class Tracer;

/**
Expand Down Expand Up @@ -132,10 +137,7 @@ class Span

// Mark the end of the Span. Only the timing of the first End call for a given Span will
// be recorded, and implementations are free to ignore all further calls.
virtual void End() noexcept = 0;

// TODO
// virtual void End(EndSpanOptions&& opts) noexcept = 0;
virtual void End(const EndSpanOptions &options = {}) noexcept = 0;

// TODO
// SpanContext context() const noexcept = 0;
Expand Down
4 changes: 2 additions & 2 deletions examples/plugin/plugin/tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Span final : public trace::Span
public:
Span(std::shared_ptr<Tracer> &&tracer,
nostd::string_view name,
const trace::StartSpanOptions &options) noexcept
const trace::StartSpanOptions & /*options*/) noexcept
: tracer_{std::move(tracer)}, name_{name}
{
std::cout << "StartSpan: " << name << "\n";
Expand All @@ -38,7 +38,7 @@ class Span final : public trace::Span

void UpdateName(nostd::string_view /*name*/) noexcept override {}

void End() noexcept override {}
void End(const trace::EndSpanOptions & /*options*/) noexcept override {}

bool IsRecording() const noexcept override { return true; }

Expand Down
Binary file added sdk/src/trace/.tracer.cc.swp
Binary file not shown.
40 changes: 39 additions & 1 deletion sdk/src/trace/span.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,37 @@ namespace sdk
{
namespace trace
{

using opentelemetry::core::SteadyTimestamp;
using opentelemetry::core::SystemTimestamp;

namespace
{
SystemTimestamp NowOrGiven(const SystemTimestamp &system)
{
if (system == SystemTimestamp())
{
return SystemTimestamp(std::chrono::system_clock::now());
}
else
{
return system;
}
}

SteadyTimestamp NowOrGiven(const SteadyTimestamp &steady)
{
if (steady == SteadyTimestamp())
{
return SteadyTimestamp(std::chrono::steady_clock::now());
}
else
{
return steady;
}
}
} // namespace

Span::Span(std::shared_ptr<Tracer> &&tracer,
std::shared_ptr<SpanProcessor> processor,
nostd::string_view name,
Expand All @@ -20,6 +51,9 @@ Span::Span(std::shared_ptr<Tracer> &&tracer,
}
processor_->OnStart(*recordable_);
recordable_->SetName(name);

recordable_->SetStartTime(NowOrGiven(options.start_system_time));
start_steady_time = NowOrGiven(options.start_steady_time);
}

Span::~Span()
Expand Down Expand Up @@ -67,13 +101,17 @@ void Span::UpdateName(nostd::string_view name) noexcept
recordable_->SetName(name);
}

void Span::End() noexcept
void Span::End(const trace_api::EndSpanOptions &options) noexcept
{
std::lock_guard<std::mutex> lock_guard{mu_};
if (recordable_ == nullptr)
{
return;
}

recordable_->SetDuration(
std::chrono::steady_clock::time_point(NowOrGiven(options.end_steady_time)) -
std::chrono::steady_clock::time_point(start_steady_time));
processor_->OnEnd(std::move(recordable_));
recordable_.reset();
}
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/trace/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Span final : public trace_api::Span

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

void End() noexcept override;
void End(const trace_api::EndSpanOptions &options = {}) noexcept override;

bool IsRecording() const noexcept override;

Expand All @@ -46,6 +46,7 @@ class Span final : public trace_api::Span
std::shared_ptr<SpanProcessor> processor_;
mutable std::mutex mu_;
std::unique_ptr<Recordable> recordable_;
opentelemetry::core::SteadyTimestamp start_steady_time;
};
} // namespace trace
} // namespace sdk
Expand Down
67 changes: 58 additions & 9 deletions sdk/test/trace/tracer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
#include <gtest/gtest.h>

using namespace opentelemetry::sdk::trace;
using opentelemetry::core::SteadyTimestamp;
using opentelemetry::core::SystemTimestamp;

/**
* A mock exporter that switches a flag once a valid recordable was received.
*/
class MockSpanExporter final : public SpanExporter
{
public:
MockSpanExporter(std::shared_ptr<std::vector<std::string>> spans_received) noexcept
MockSpanExporter(std::shared_ptr<std::vector<std::unique_ptr<SpanData>>> spans_received) noexcept
: spans_received_(spans_received)
{}

Expand All @@ -29,7 +31,7 @@ class MockSpanExporter final : public SpanExporter
auto span = std::unique_ptr<SpanData>(static_cast<SpanData *>(recordable.release()));
if (span != nullptr)
{
spans_received_->push_back(std::string(span->GetName()));
spans_received_->push_back(std::move(span));
}
}

Expand All @@ -40,15 +42,25 @@ class MockSpanExporter final : public SpanExporter
{}

private:
std::shared_ptr<std::vector<std::string>> spans_received_;
std::shared_ptr<std::vector<std::unique_ptr<SpanData>>> spans_received_;
};

TEST(Tracer, ToMockSpanExporter)
namespace
{
std::shared_ptr<Tracer> initTracer(
std::shared_ptr<std::vector<std::unique_ptr<SpanData>>> &received)
{
std::shared_ptr<std::vector<std::string>> spans_received(new std::vector<std::string>);
std::unique_ptr<SpanExporter> exporter(new MockSpanExporter(spans_received));
std::unique_ptr<SpanExporter> exporter(new MockSpanExporter(received));
std::shared_ptr<SimpleSpanProcessor> processor(new SimpleSpanProcessor(std::move(exporter)));
std::shared_ptr<Tracer> tracer(new Tracer(processor));
return std::shared_ptr<Tracer>(new Tracer(processor));
}
} // namespace

TEST(Tracer, ToMockSpanExporter)
{
std::shared_ptr<std::vector<std::unique_ptr<SpanData>>> spans_received(
new std::vector<std::unique_ptr<SpanData>>);
auto tracer = initTracer(spans_received);

auto span_first = tracer->StartSpan("span 1");
auto span_second = tracer->StartSpan("span 2");
Expand All @@ -57,9 +69,46 @@ TEST(Tracer, ToMockSpanExporter)

span_second->End();
ASSERT_EQ(1, spans_received->size());
ASSERT_EQ("span 2", spans_received->at(0));
ASSERT_EQ("span 2", spans_received->at(0)->GetName());

span_first->End();
ASSERT_EQ(2, spans_received->size());
ASSERT_EQ("span 1", spans_received->at(1));
ASSERT_EQ("span 1", spans_received->at(1)->GetName());
}

TEST(Tracer, StartSpan)
{
std::shared_ptr<std::vector<std::unique_ptr<SpanData>>> spans_received(
new std::vector<std::unique_ptr<SpanData>>);
auto tracer = initTracer(spans_received);

tracer->StartSpan("span 1")->End();

ASSERT_EQ(1, spans_received->size());

auto &span_data = spans_received->at(0);
ASSERT_LT(std::chrono::nanoseconds(0), span_data->GetStartTime().time_since_epoch());
ASSERT_LT(std::chrono::nanoseconds(0), span_data->GetDuration());
}

TEST(Tracer, StartSpanWithOptions)
{
std::shared_ptr<std::vector<std::unique_ptr<SpanData>>> spans_received(
new std::vector<std::unique_ptr<SpanData>>);
auto tracer = initTracer(spans_received);

opentelemetry::trace::StartSpanOptions start;
start.start_system_time = SystemTimestamp(std::chrono::nanoseconds(300));
start.start_steady_time = SteadyTimestamp(std::chrono::nanoseconds(10));

opentelemetry::trace::EndSpanOptions end;
end.end_steady_time = SteadyTimestamp(std::chrono::nanoseconds(40));

tracer->StartSpan("span 1", start)->End(end);

ASSERT_EQ(1, spans_received->size());

auto &span_data = spans_received->at(0);
ASSERT_EQ(std::chrono::nanoseconds(300), span_data->GetStartTime().time_since_epoch());
ASSERT_EQ(std::chrono::nanoseconds(30), span_data->GetDuration());
}

0 comments on commit 9db466a

Please sign in to comment.