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

Commit ba63106

Browse files
authored
Add view data expiry. (#452)
Fixes #451.
1 parent 33339f0 commit ba63106

File tree

5 files changed

+114
-2
lines changed

5 files changed

+114
-2
lines changed

opencensus/stats/internal/view_data_impl.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ ViewDataImpl::ViewDataImpl(absl::Time start_time,
6565
aggregation_window_(descriptor.aggregation_window_),
6666
type_(TypeForDescriptor(descriptor)),
6767
start_times_(),
68+
expiry_duration_(descriptor.expiry_duration_),
6869
start_time_(start_time) {
6970
switch (type_) {
7071
case Type::kDouble: {
@@ -195,6 +196,8 @@ void ViewDataImpl::Merge(const std::vector<std::string>& tag_values,
195196
const MeasureData& data, absl::Time now) {
196197
// A value is set here. Set a start time if it is unset.
197198
SetStartTimeIfUnset(tag_values, now);
199+
SetUpdateTime(tag_values, now);
200+
PurgeExpired(now);
198201
switch (type_) {
199202
case Type::kDouble: {
200203
if (aggregation_.type() == Aggregation::Type::kSum) {
@@ -302,5 +305,60 @@ ViewDataImpl::ViewDataImpl(ViewDataImpl* source, absl::Time now)
302305
}
303306
}
304307

308+
void ViewDataImpl::SetUpdateTime(const std::vector<std::string>& tag_values,
309+
absl::Time now) {
310+
if (expiry_duration_ == absl::ZeroDuration()) {
311+
// No need to track last update time if expiry duration is not set.
312+
return;
313+
}
314+
315+
auto update_time_map_iter = update_time_entries_.find(tag_values);
316+
if (update_time_map_iter == update_time_entries_.end()) {
317+
// The timeseries is not tracked, add it to the update time list and map.
318+
update_times_.emplace_front(now, tag_values);
319+
update_time_entries_[tag_values] = update_times_.begin();
320+
} else {
321+
// The timeseries is tracked, update its updated time and move it to the
322+
// front of the list.
323+
auto update_time_list_iter = update_time_map_iter->second;
324+
update_time_list_iter->first = now;
325+
update_times_.splice(update_times_.begin(), update_times_,
326+
update_time_list_iter);
327+
}
328+
}
329+
330+
void ViewDataImpl::PurgeExpired(absl::Time now) {
331+
if (expiry_duration_ == absl::ZeroDuration() || update_times_.empty()) {
332+
// No need to remove expired entries since either expiry is not set or there
333+
// is no data entry yet.
334+
return;
335+
}
336+
// Remove data that has not been updated for expiry.
337+
while (now - update_times_.back().first > expiry_duration_) {
338+
const auto& tags = update_times_.back().second;
339+
update_time_entries_.erase(tags);
340+
start_times_.erase(tags);
341+
switch (type_) {
342+
case Type::kDouble: {
343+
double_data_.erase(tags);
344+
break;
345+
}
346+
case Type::kInt64: {
347+
int_data_.erase(tags);
348+
break;
349+
}
350+
case Type::kDistribution: {
351+
distribution_data_.erase(tags);
352+
break;
353+
}
354+
case Type::kStatsObject: {
355+
interval_data_.erase(tags);
356+
break;
357+
}
358+
}
359+
update_times_.pop_back();
360+
}
361+
}
362+
305363
} // namespace stats
306364
} // namespace opencensus

opencensus/stats/internal/view_data_impl.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ class ViewDataImpl {
134134
}
135135
}
136136

137+
// If expiry duration is set, keep track of the last update time of each view
138+
// data.
139+
void SetUpdateTime(const std::vector<std::string>& tag_values,
140+
absl::Time now);
141+
142+
// Purge view data that has not been updated for expiry duration.
143+
void PurgeExpired(absl::Time now);
144+
137145
const Aggregation aggregation_;
138146
const AggregationWindow aggregation_window_;
139147
const Type type_;
@@ -147,6 +155,16 @@ class ViewDataImpl {
147155
// A start time for each timeseries/tag map.
148156
DataMap<absl::Time> start_times_;
149157

158+
using UpdateTimeList =
159+
std::list<std::pair<absl::Time, std::vector<std::string>>>;
160+
161+
// A list of last update time for each timeseries.
162+
UpdateTimeList update_times_;
163+
// A map from view data tags to the last update time list iterator.
164+
DataMap<UpdateTimeList::iterator> update_time_entries_;
165+
166+
const absl::Duration expiry_duration_;
167+
150168
// DEPRECATED: Legacy start_time_ for the entire view.
151169
// This should be deleted if custom exporters are updated to
152170
// use start_times_ and stop depending on this field

opencensus/stats/internal/view_data_impl_test.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,28 @@ TEST(ViewDataImplTest, StatsObjectToDistribution) {
301301
EXPECT_THAT(distribution_2_2.bucket_counts(), ::testing::ElementsAre(0, 0));
302302
}
303303

304+
TEST(ViewDataImplTest, ViewDataExpiry) {
305+
const absl::Time start_time = absl::UnixEpoch();
306+
const auto descriptor = ViewDescriptor()
307+
.set_aggregation(Aggregation::Sum())
308+
.set_expiry_duration(absl::Seconds(1));
309+
ViewDataImpl data(start_time, descriptor);
310+
const std::vector<std::string> tags1({"value1", "value2a"});
311+
const std::vector<std::string> tags2({"value1", "value2b"});
312+
313+
AddToViewDataImpl(1, tags1, start_time, {}, &data);
314+
AddToViewDataImpl(1, tags2, start_time, {}, &data);
315+
316+
EXPECT_THAT(data.double_data(),
317+
::testing::UnorderedElementsAre(::testing::Pair(tags1, 1),
318+
::testing::Pair(tags2, 1)));
319+
320+
AddToViewDataImpl(1, tags1, start_time + absl::Seconds(2), {}, &data);
321+
322+
EXPECT_THAT(data.double_data(),
323+
::testing::UnorderedElementsAre(::testing::Pair(tags1, 2)));
324+
}
325+
304326
} // namespace
305327
} // namespace stats
306328
} // namespace opencensus

opencensus/stats/internal/view_descriptor.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ ViewDescriptor& ViewDescriptor::set_description(absl::string_view description) {
7474
return *this;
7575
}
7676

77+
ViewDescriptor& ViewDescriptor::set_expiry_duration(
78+
absl::Duration expiry_duration) {
79+
expiry_duration_ = expiry_duration;
80+
return *this;
81+
}
82+
7783
void ViewDescriptor::RegisterForExport() const {
7884
if (aggregation_window_.type() == AggregationWindow::Type::kCumulative) {
7985
StatsExporterImpl::Get()->AddView(*this);
@@ -93,14 +99,16 @@ std::string ViewDescriptor::DebugString() const {
9399
[](std::string* out, opencensus::tags::TagKey key) {
94100
return out->append(key.name());
95101
}),
96-
"\n description: \"", description_, "\"");
102+
"\n description: \"", description_, "\"",
103+
"\n expiry duration: ", absl::FormatDuration(expiry_duration_));
97104
}
98105

99106
bool ViewDescriptor::operator==(const ViewDescriptor& other) const {
100107
return name_ == other.name_ && measure_id_ == other.measure_id_ &&
101108
aggregation_ == other.aggregation_ &&
102109
aggregation_window_ == other.aggregation_window_ &&
103-
columns_ == other.columns_ && description_ == other.description_;
110+
columns_ == other.columns_ && description_ == other.description_ &&
111+
expiry_duration_ == other.expiry_duration_;
104112
}
105113

106114
} // namespace stats

opencensus/stats/view_descriptor.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ class ViewDescriptor final {
8282
ViewDescriptor& set_description(absl::string_view description);
8383
const std::string& description() const { return description_; }
8484

85+
// Sets the desired lifetime of the view's data. If the view data is not
86+
// updated at any point during this duration, it will be removed from the set
87+
// of data recorded by the view when periodic aggregation happens.
88+
ViewDescriptor& set_expiry_duration(absl::Duration expiry_duration);
89+
8590
//////////////////////////////////////////////////////////////////////////////
8691
// View registration
8792

@@ -113,6 +118,7 @@ class ViewDescriptor final {
113118
AggregationWindow aggregation_window_;
114119
std::vector<opencensus::tags::TagKey> columns_;
115120
std::string description_;
121+
absl::Duration expiry_duration_;
116122
};
117123

118124
} // namespace stats

0 commit comments

Comments
 (0)