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

Commit eabb06a

Browse files
authored
Make trace export interval and batch size configurable at runtime. (#421)
Fixes #420.
1 parent 67c7c1a commit eabb06a

File tree

6 files changed

+78
-29
lines changed

6 files changed

+78
-29
lines changed

opencensus/trace/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ opencensus_lib(
4949
absl::time
5050
absl::span)
5151

52+
# Define NOMINMAX to fix build errors when compiling with MSVC.
53+
target_compile_definitions(opencensus_trace PUBLIC
54+
$<$<CXX_COMPILER_ID:MSVC>:NOMINMAX>)
55+
5256
opencensus_lib(
5357
trace_b3
5458
PUBLIC

opencensus/trace/exporter/span_exporter.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <memory>
1919
#include <vector>
2020

21+
#include "absl/time/time.h"
2122
#include "opencensus/trace/exporter/span_data.h"
2223

2324
namespace opencensus {
@@ -27,6 +28,22 @@ namespace exporter {
2728
// SpanExporter allows Exporters to register. Thread-safe.
2829
class SpanExporter final {
2930
public:
31+
// Sets the batch size when exporting traces. Takes effect after the next
32+
// batch starts. This is not a strict limit, the generated batch may be
33+
// slightly larger. If the interval expires before the batch fills up, the
34+
// batch will be smaller.
35+
//
36+
// Warning: this API may be removed in future, in favor of configuring this
37+
// per-exporter.
38+
static void SetBatchSize(int size);
39+
40+
// Sets the interval between exporting batches of traces. Takes effect after
41+
// the next batch starts.
42+
//
43+
// Warning: this API may be removed in future, in favor of configuring this
44+
// per-exporter.
45+
static void SetInterval(absl::Duration interval);
46+
3047
// Handlers allow different tracing services to export recorded data for
3148
// sampled spans in their own format. Every exporter must provide a static
3249
// Register() method that takes any arguments needed by the exporter (e.g. a
@@ -41,6 +58,7 @@ class SpanExporter final {
4158
static void RegisterHandler(std::unique_ptr<Handler> handler);
4259

4360
private:
61+
SpanExporter() = delete;
4462
friend class SpanExporterTestPeer;
4563

4664
// Forces an export, only for testing purposes.

opencensus/trace/internal/span_exporter.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,23 @@
1717
#include <memory>
1818
#include <utility>
1919

20+
#include "absl/time/time.h"
2021
#include "opencensus/trace/internal/span_exporter_impl.h"
2122

2223
namespace opencensus {
2324
namespace trace {
2425
namespace exporter {
2526

27+
// static
28+
void SpanExporter::SetBatchSize(int size) {
29+
SpanExporterImpl::Get()->SetBatchSize(size);
30+
}
31+
32+
// static
33+
void SpanExporter::SetInterval(absl::Duration interval) {
34+
SpanExporterImpl::Get()->SetInterval(interval);
35+
}
36+
2637
// static
2738
void SpanExporter::RegisterHandler(std::unique_ptr<Handler> handler) {
2839
SpanExporterImpl::Get()->RegisterHandler(std::move(handler));

opencensus/trace/internal/span_exporter_impl.cc

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "opencensus/trace/internal/span_exporter_impl.h"
1616

17+
#include <algorithm>
1718
#include <utility>
1819

1920
#include "absl/synchronization/mutex.h"
@@ -24,17 +25,20 @@ namespace opencensus {
2425
namespace trace {
2526
namespace exporter {
2627

27-
SpanExporterImpl* SpanExporterImpl::span_exporter_ = nullptr;
28-
2928
SpanExporterImpl* SpanExporterImpl::Get() {
30-
static SpanExporterImpl* global_span_exporter_impl = new SpanExporterImpl(
31-
kDefaultBufferSize, absl::Milliseconds(kIntervalWaitTimeInMillis));
29+
static SpanExporterImpl* global_span_exporter_impl = new SpanExporterImpl;
3230
return global_span_exporter_impl;
3331
}
3432

35-
SpanExporterImpl::SpanExporterImpl(uint32_t buffer_size,
36-
absl::Duration interval)
37-
: buffer_size_(buffer_size), interval_(interval) {}
33+
void SpanExporterImpl::SetBatchSize(int size) {
34+
absl::MutexLock l(&handler_mu_);
35+
batch_size_ = std::max(1, size);
36+
}
37+
38+
void SpanExporterImpl::SetInterval(absl::Duration interval) {
39+
absl::MutexLock l(&handler_mu_);
40+
interval_ = std::max(absl::Seconds(1), interval);
41+
}
3842

3943
void SpanExporterImpl::RegisterHandler(
4044
std::unique_ptr<SpanExporter::Handler> handler) {
@@ -59,36 +63,43 @@ void SpanExporterImpl::StartExportThread() {
5963
collect_spans_ = true;
6064
}
6165

62-
bool SpanExporterImpl::IsBufferFull() const {
66+
bool SpanExporterImpl::IsBatchFull() const {
6367
span_mu_.AssertHeld();
64-
return spans_.size() >= buffer_size_;
68+
return spans_.size() >= cached_batch_size_;
6569
}
6670

6771
void SpanExporterImpl::RunWorkerLoop() {
68-
std::vector<opencensus::trace::exporter::SpanData> span_data_;
69-
std::vector<std::shared_ptr<opencensus::trace::SpanImpl>> batch_;
72+
std::vector<opencensus::trace::exporter::SpanData> span_data;
73+
std::vector<std::shared_ptr<opencensus::trace::SpanImpl>> batch;
7074
// Thread loops forever.
7175
// TODO: Add in shutdown mechanism.
72-
absl::Time next_forced_export_time = absl::Now() + interval_;
7376
while (true) {
77+
int size;
78+
absl::Time next_forced_export_time;
79+
{
80+
// Start of loop, update batch size and interval.
81+
absl::MutexLock l(&handler_mu_);
82+
size = batch_size_;
83+
next_forced_export_time = absl::Now() + interval_;
84+
}
7485
{
7586
absl::MutexLock l(&span_mu_);
87+
cached_batch_size_ = size;
7688
// Wait until batch is full or interval time has been exceeded.
7789
span_mu_.AwaitWithDeadline(
78-
absl::Condition(this, &SpanExporterImpl::IsBufferFull),
90+
absl::Condition(this, &SpanExporterImpl::IsBatchFull),
7991
next_forced_export_time);
80-
next_forced_export_time = absl::Now() + interval_;
8192
if (spans_.empty()) {
8293
continue;
8394
}
84-
std::swap(batch_, spans_);
95+
std::swap(batch, spans_);
8596
}
86-
for (const auto& span : batch_) {
87-
span_data_.emplace_back(span->ToSpanData());
97+
for (const auto& span : batch) {
98+
span_data.emplace_back(span->ToSpanData());
8899
}
89-
batch_.clear();
90-
Export(span_data_);
91-
span_data_.clear();
100+
batch.clear();
101+
Export(span_data);
102+
span_data.clear();
92103
}
93104
}
94105

opencensus/trace/internal/span_exporter_impl.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class SpanExporterImpl {
4444
// Returns the global instance of SpanExporterImpl.
4545
static SpanExporterImpl* Get();
4646

47+
void SetBatchSize(int size);
48+
void SetInterval(absl::Duration interval);
49+
4750
// A shared_ptr to the span is added to a list. The actual conversion to
4851
// SpanData will take place at a later time via the background thread. This
4952
// is intended to be called at the Span::End().
@@ -53,11 +56,8 @@ class SpanExporterImpl {
5356
// initialization.
5457
void RegisterHandler(std::unique_ptr<SpanExporter::Handler> handler);
5558

56-
static constexpr uint32_t kDefaultBufferSize = 64;
57-
static constexpr uint32_t kIntervalWaitTimeInMillis = 5000;
58-
5959
private:
60-
SpanExporterImpl(uint32_t buffer_size, absl::Duration interval);
60+
SpanExporterImpl() = default;
6161
SpanExporterImpl(const SpanExporterImpl&) = delete;
6262
SpanExporterImpl(SpanExporterImpl&&) = delete;
6363
SpanExporterImpl& operator=(const SpanExporterImpl&) = delete;
@@ -75,14 +75,15 @@ class SpanExporterImpl {
7575
// returns when complete.
7676
void ExportForTesting();
7777

78-
// Returns true if the spans_ buffer has filled up.
79-
bool IsBufferFull() const;
78+
// Returns true if the spans_ batch is full.
79+
bool IsBatchFull() const;
8080

81-
static SpanExporterImpl* span_exporter_;
82-
const uint32_t buffer_size_;
83-
const absl::Duration interval_;
8481
mutable absl::Mutex span_mu_;
8582
mutable absl::Mutex handler_mu_;
83+
int batch_size_ GUARDED_BY(handler_mu_) = 64;
84+
absl::Duration interval_ GUARDED_BY(handler_mu_) = absl::Seconds(5);
85+
// Updated in RunWorkerLoop and protected by span_mu_ instead of handler_mu_.
86+
int cached_batch_size_ GUARDED_BY(span_mu_);
8687
std::vector<std::shared_ptr<opencensus::trace::SpanImpl>> spans_
8788
GUARDED_BY(span_mu_);
8889
std::vector<std::unique_ptr<SpanExporter::Handler>> handlers_

opencensus/trace/internal/span_exporter_test.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "absl/memory/memory.h"
1818
#include "absl/synchronization/mutex.h"
1919
#include "absl/time/clock.h"
20+
#include "absl/time/time.h"
2021
#include "gtest/gtest.h"
2122
#include "opencensus/trace/exporter/span_data.h"
2223
#include "opencensus/trace/sampler.h"
@@ -63,6 +64,9 @@ class MyExporter : public exporter::SpanExporter::Handler {
6364
class SpanExporterTest : public ::testing::Test {
6465
protected:
6566
static void SetUpTestSuite() {
67+
exporter::SpanExporter::SetBatchSize(1);
68+
exporter::SpanExporter::SetInterval(absl::Seconds(1));
69+
6670
// Only register once.
6771
MyExporter::Register();
6872
}

0 commit comments

Comments
 (0)