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

Commit 7b7c6b1

Browse files
committed
Implement Span::Abandon().
1 parent 858195c commit 7b7c6b1

File tree

6 files changed

+61
-9
lines changed

6 files changed

+61
-9
lines changed

opencensus/trace/internal/span.cc

+12-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ class SpanGenerator {
9494
SpanContext context(trace_id, span_id, trace_options);
9595
SpanImpl* impl = nullptr;
9696
if (trace_options.IsSampled()) {
97-
// Only Spans that are sampled are backed by a SpanImpl.
97+
// Only Spans that started off sampled are backed by a SpanImpl.
98+
// They can be abandoned later.
9899
impl =
99100
new SpanImpl(context, TraceConfigImpl::Get()->current_trace_params(),
100101
name, parent_span_id, has_remote_parent);
@@ -216,10 +217,20 @@ void Span::End() const {
216217
}
217218
exporter::RunningSpanStoreImpl::Get()->RemoveSpan(span_impl_);
218219
exporter::LocalSpanStoreImpl::Get()->AddSpan(span_impl_);
220+
// SpanExporterImpl checks if span_impl_ is sampled for export.
219221
exporter::SpanExporterImpl::Get()->AddSpan(span_impl_);
220222
}
221223
}
222224

225+
void Span::Abandon() {
226+
if (IsRecording()) {
227+
context_ = SpanContext(context_.trace_id(), context_.span_id(),
228+
context_.trace_options().WithSampling(false));
229+
span_impl_->MarkAbandoned();
230+
End();
231+
}
232+
}
233+
223234
const SpanContext& Span::context() const { return context_; }
224235

225236
bool Span::IsSampled() const { return context_.trace_options().IsSampled(); }

opencensus/trace/internal/span_exporter_impl.cc

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ void SpanExporterImpl::AddSpan(
4949
const std::shared_ptr<opencensus::trace::SpanImpl>& span_impl) {
5050
absl::MutexLock l(&span_mu_);
5151
if (!collect_spans_) return;
52+
if (!span_impl->IsSampled()) return;
5253
spans_.emplace_back(span_impl);
5354
}
5455

opencensus/trace/internal/span_impl.cc

+15
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ void SpanImpl::SetName(absl::string_view name) {
144144
}
145145
}
146146

147+
void SpanImpl::MarkAbandoned() {
148+
absl::MutexLock l(&mu_);
149+
context_ = SpanContext(context_.trace_id(), context_.span_id(),
150+
context_.trace_options().WithSampling(false));
151+
}
152+
147153
bool SpanImpl::End() {
148154
absl::MutexLock l(&mu_);
149155
if (has_ended_) {
@@ -161,6 +167,15 @@ bool SpanImpl::HasEnded() const {
161167
return has_ended_;
162168
}
163169

170+
bool SpanImpl::IsSampled() const {
171+
return context().trace_options().IsSampled();
172+
}
173+
174+
SpanContext SpanImpl::context() const {
175+
absl::MutexLock l(&mu_);
176+
return context_;
177+
}
178+
164179
exporter::SpanData SpanImpl::ToSpanData() const {
165180
absl::MutexLock l(&mu_);
166181
// Make a deep copy of attributes.

opencensus/trace/internal/span_impl.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -87,20 +87,27 @@ class SpanImpl final {
8787

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

90+
void MarkAbandoned() LOCKS_EXCLUDED(mu_);
91+
9092
// Returns true on success (if this is the first time the Span has ended) and
9193
// also marks the end of the Span and sets its end_time_.
9294
bool End() LOCKS_EXCLUDED(mu_);
9395

94-
// Returns true if the span has ended.
96+
// Returns true if the Span has ended.
9597
bool HasEnded() const LOCKS_EXCLUDED(mu_);
9698

99+
// Returns true if the Span is sampled for export. Returns false if the Span
100+
// was abandoned.
101+
bool IsSampled() const LOCKS_EXCLUDED(mu_);
102+
97103
absl::string_view name() const { return name_; }
98104

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

102108
// Returns the SpanContext associated with this Span.
103-
SpanContext context() const { return context_; }
109+
// The trace_options do reflect MarkAbandoned().
110+
SpanContext context() const LOCKS_EXCLUDED(mu_);
104111

105112
SpanId parent_span_id() const { return parent_span_id_; }
106113

@@ -126,7 +133,7 @@ class SpanImpl final {
126133
// a root span.
127134
const SpanId parent_span_id_;
128135
// TraceId, SpanId, and TraceOptions for the current span.
129-
const SpanContext context_;
136+
SpanContext context_ GUARDED_BY(mu_);
130137
// Queue of recorded annotations.
131138
TraceEvents<EventWithTime<exporter::Annotation>> annotations_ GUARDED_BY(mu_);
132139
// Queue of recorded network events.
@@ -138,6 +145,8 @@ class SpanImpl final {
138145
AttributeList attributes_ GUARDED_BY(mu_);
139146
// Marks if the span has ended.
140147
bool has_ended_ GUARDED_BY(mu_);
148+
// Marks if the span was abandoned.
149+
bool is_abandoned_ GUARDED_BY(mu_);
141150
// True if the parent Span is in a different process.
142151
const bool remote_parent_;
143152
};

opencensus/trace/internal/span_test.cc

+10
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,16 @@ TEST(SpanTest, BlankSpan) {
365365
span.End();
366366
}
367367

368+
TEST(SpanTest, Abandon) {
369+
AlwaysSampler sampler;
370+
auto span = Span::StartSpan("SpanName", /*parent=*/nullptr, {&sampler});
371+
EXPECT_TRUE(span.IsSampled());
372+
span.Abandon();
373+
EXPECT_FALSE(span.IsSampled());
374+
auto data = SpanTestPeer::ToSpanData(&span);
375+
EXPECT_FALSE(data.context().trace_options().IsSampled());
376+
}
377+
368378
} // namespace
369379
} // namespace trace
370380
} // namespace opencensus

opencensus/trace/span.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ struct StartSpanOptions {
7979
// implementation-defined data structure, hence all operations on it are marked
8080
// const.
8181
//
82-
// Span is thread-compatible. If swap() and operator= are avoided, everything
83-
// else is thread-safe. Avoid mutating Span objects in-place; treat them like
84-
// read-only handles. When using multiple threads, give each thread a copy of
85-
// the Span.
82+
// Span is thread-compatible. Avoid mutating Span objects in-place; treat them
83+
// like read-only handles. When using multiple threads, give each thread a copy
84+
// of the Span.
85+
//
86+
// Almost everything is thread-safe except: swap(), operator=, Abandon().
8687
//
8788
// As an alternative to explicitly passing Span objects between functions,
8889
// consider using Context. (see the ../context/ directory).
@@ -154,13 +155,18 @@ class Span final {
154155
void SetStatus(StatusCode canonical_code,
155156
absl::string_view message = "") const;
156157

157-
// Set the span name.
158+
// Set the Span name.
158159
void SetName(absl::string_view name) const;
159160

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

165+
// If the Span was sampled, un-samples it and End()s it. Note that other
166+
// copies of this Span, and child spans, do not become unsampled.
167+
// TODO(opencensus-specs): Should Abandon() not call End()?
168+
void Abandon();
169+
164170
// Returns the SpanContext associated with this Span.
165171
const SpanContext& context() const;
166172

0 commit comments

Comments
 (0)