Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Implement Span::Abandon(). #339

Open
wants to merge 4 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
13 changes: 12 additions & 1 deletion opencensus/trace/internal/span.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ class SpanGenerator {
SpanContext context(trace_id, span_id, trace_options);
SpanImpl* impl = nullptr;
if (trace_options.IsSampled()) {
// Only Spans that are sampled are backed by a SpanImpl.
// Only Spans that started off sampled are backed by a SpanImpl.
// They can be abandoned later.
impl =
new SpanImpl(context, TraceConfigImpl::Get()->current_trace_params(),
name, parent_span_id, has_remote_parent);
Expand Down Expand Up @@ -216,10 +217,20 @@ void Span::End() const {
}
exporter::RunningSpanStoreImpl::Get()->RemoveSpan(span_impl_);
exporter::LocalSpanStoreImpl::Get()->AddSpan(span_impl_);
// SpanExporterImpl checks if span_impl_ is sampled for export.
exporter::SpanExporterImpl::Get()->AddSpan(span_impl_);
}
}

void Span::Abandon() {
context_ = SpanContext(context_.trace_id(), context_.span_id(),
context_.trace_options().WithSampling(false));
if (IsRecording()) {
span_impl_->MarkAbandoned();
End();
}
}

const SpanContext& Span::context() const { return context_; }

bool Span::IsSampled() const { return context_.trace_options().IsSampled(); }
Expand Down
1 change: 1 addition & 0 deletions opencensus/trace/internal/span_exporter_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void SpanExporterImpl::AddSpan(
const std::shared_ptr<opencensus::trace::SpanImpl>& span_impl) {
absl::MutexLock l(&span_mu_);
if (!collect_spans_) return;
if (!span_impl->IsSampled()) return;
spans_.emplace_back(span_impl);
}

Expand Down
15 changes: 15 additions & 0 deletions opencensus/trace/internal/span_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ void SpanImpl::SetName(absl::string_view name) {
}
}

void SpanImpl::MarkAbandoned() {
absl::MutexLock l(&mu_);
context_ = SpanContext(context_.trace_id(), context_.span_id(),
context_.trace_options().WithSampling(false));
}

bool SpanImpl::End() {
absl::MutexLock l(&mu_);
if (has_ended_) {
Expand All @@ -161,6 +167,15 @@ bool SpanImpl::HasEnded() const {
return has_ended_;
}

bool SpanImpl::IsSampled() const {
return context().trace_options().IsSampled();
}

SpanContext SpanImpl::context() const {
absl::MutexLock l(&mu_);
return context_;
}

exporter::SpanData SpanImpl::ToSpanData() const {
absl::MutexLock l(&mu_);
// Make a deep copy of attributes.
Expand Down
13 changes: 10 additions & 3 deletions opencensus/trace/internal/span_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,27 @@ class SpanImpl final {

void SetName(absl::string_view name) LOCKS_EXCLUDED(mu_);

void MarkAbandoned() LOCKS_EXCLUDED(mu_);

// Returns true on success (if this is the first time the Span has ended) and
// also marks the end of the Span and sets its end_time_.
bool End() LOCKS_EXCLUDED(mu_);

// Returns true if the span has ended.
// Returns true if the Span has ended.
bool HasEnded() const LOCKS_EXCLUDED(mu_);

// Returns true if the Span is sampled for export. Returns false if the Span
// was abandoned.
bool IsSampled() const LOCKS_EXCLUDED(mu_);

absl::string_view name() const { return name_; }

// Returns the name of the span as a constref string.
const std::string& name_constref() const { return name_; }

// Returns the SpanContext associated with this Span.
SpanContext context() const { return context_; }
// The trace_options do reflect MarkAbandoned().
SpanContext context() const LOCKS_EXCLUDED(mu_);

SpanId parent_span_id() const { return parent_span_id_; }

Expand All @@ -126,7 +133,7 @@ class SpanImpl final {
// a root span.
const SpanId parent_span_id_;
// TraceId, SpanId, and TraceOptions for the current span.
const SpanContext context_;
SpanContext context_ GUARDED_BY(mu_);
// Queue of recorded annotations.
TraceEvents<EventWithTime<exporter::Annotation>> annotations_ GUARDED_BY(mu_);
// Queue of recorded network events.
Expand Down
10 changes: 10 additions & 0 deletions opencensus/trace/internal/span_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,16 @@ TEST(SpanTest, BlankSpan) {
span.End();
}

TEST(SpanTest, Abandon) {
AlwaysSampler sampler;
auto span = Span::StartSpan("SpanName", /*parent=*/nullptr, {&sampler});
EXPECT_TRUE(span.IsSampled());
span.Abandon();
EXPECT_FALSE(span.IsSampled());
auto data = SpanTestPeer::ToSpanData(&span);
EXPECT_FALSE(data.context().trace_options().IsSampled());
}

} // namespace
} // namespace trace
} // namespace opencensus
22 changes: 17 additions & 5 deletions opencensus/trace/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ struct StartSpanOptions {
// implementation-defined data structure, hence all operations on it are marked
// const.
//
// Span is thread-compatible. If swap() and operator= are avoided, everything
// else is thread-safe. Avoid mutating Span objects in-place; treat them like
// read-only handles. When using multiple threads, give each thread a copy of
// the Span.
// Span is thread-compatible. Avoid mutating Span objects in-place; treat them
// like read-only handles. When using multiple threads, give each thread a copy
// of the Span.
//
// Almost everything is thread-safe except: swap(), operator=, Abandon().
//
// As an alternative to explicitly passing Span objects between functions,
// consider using Context. (see the ../context/ directory).
Expand Down Expand Up @@ -154,13 +155,24 @@ class Span final {
void SetStatus(StatusCode canonical_code,
absl::string_view message = "") const;

// Set the span name.
// Set the Span name.
void SetName(absl::string_view name) const;

// Marks the end of a Span. No further changes can be made to the Span after
// End is called.
void End() const;

// Mark this Span as not sampled and End() it. Note that other copies of this
// Span object will still think they're sampled, and any child spans that have
// already been created will not be affected. The underlying data for just
// this Span will not be exported.
//
// Use of Abandon() is discouraged. Prefer to make the sampling decision at
// Start time.
//
// TODO(opencensus-specs): Should Abandon() not call End()?
void Abandon();

// Returns the SpanContext associated with this Span.
const SpanContext& context() const;

Expand Down