Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-order functions in stats_impl to group classes together #4004

Merged
merged 14 commits into from
Aug 1, 2018
Merged
Show file tree
Hide file tree
Changes from 4 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
304 changes: 171 additions & 133 deletions source/common/stats/stats_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,6 @@ bool regexStartsWithDot(absl::string_view regex) {

} // namespace

// Normally the compiler would do this, but because name_ is a flexible-array-length
// element, the compiler can't. RawStatData is put into an array in HotRestartImpl, so
// it's important that each element starts on the required alignment for the type.
uint64_t RawStatData::structSize(uint64_t name_size) {
return roundUpMultipleNaturalAlignment(sizeof(RawStatData) + name_size + 1);
}

uint64_t RawStatData::structSizeWithOptions(const StatsOptions& stats_options) {
return structSize(stats_options.maxNameLength());
}

std::string Utility::sanitizeStatsName(const std::string& name) {
std::string stats_name = name;
std::replace(stats_name.begin(), stats_name.end(), ':', '_');
std::replace(stats_name.begin(), stats_name.end(), '\0', '_');
return stats_name;
}

TagExtractorImpl::TagExtractorImpl(const std::string& name, const std::string& regex,
const std::string& substr)
: name_(name), prefix_(std::string(extractRegexPrefix(regex))), substr_(substr),
Expand Down Expand Up @@ -135,92 +117,6 @@ bool TagExtractorImpl::extractTag(const std::string& stat_name, std::vector<Tag>
return false;
}

HeapStatData::HeapStatData(absl::string_view key) : name_(key.data(), key.size()) {}

HeapStatData* HeapStatDataAllocator::alloc(absl::string_view name) {
// Any expected truncation of name is done at the callsite. No truncation is
// required to use this allocator.
auto data = std::make_unique<HeapStatData>(name);
Thread::ReleasableLockGuard lock(mutex_);
auto ret = stats_.insert(data.get());
HeapStatData* existing_data = *ret.first;
lock.release();

if (ret.second) {
return data.release();
}
++existing_data->ref_count_;
return existing_data;
}

/**
* Counter implementation that wraps a StatData. StatData must have data members:
* std::atomic<int64_t> value_;
* std::atomic<int64_t> pending_increment_;
* std::atomic<int16_t> flags_;
* std::atomic<int16_t> ref_count_;
*/
template <class StatData> class CounterImpl : public Counter, public MetricImpl {
public:
CounterImpl(StatData& data, StatDataAllocatorImpl<StatData>& alloc,
std::string&& tag_extracted_name, std::vector<Tag>&& tags)
: MetricImpl(data.name_, std::move(tag_extracted_name), std::move(tags)), data_(data),
alloc_(alloc) {}
~CounterImpl() { alloc_.free(data_); }

// Stats::Counter
void add(uint64_t amount) override {
data_.value_ += amount;
data_.pending_increment_ += amount;
data_.flags_ |= Flags::Used;
}

void inc() override { add(1); }
uint64_t latch() override { return data_.pending_increment_.exchange(0); }
void reset() override { data_.value_ = 0; }
bool used() const override { return data_.flags_ & Flags::Used; }
uint64_t value() const override { return data_.value_; }

private:
StatData& data_;
StatDataAllocatorImpl<StatData>& alloc_;
};

/**
* Gauge implementation that wraps a StatData.
*/
template <class StatData> class GaugeImpl : public Gauge, public MetricImpl {
public:
GaugeImpl(StatData& data, StatDataAllocatorImpl<StatData>& alloc,
std::string&& tag_extracted_name, std::vector<Tag>&& tags)
: MetricImpl(data.name_, std::move(tag_extracted_name), std::move(tags)), data_(data),
alloc_(alloc) {}
~GaugeImpl() { alloc_.free(data_); }

// Stats::Gauge
virtual void add(uint64_t amount) override {
data_.value_ += amount;
data_.flags_ |= Flags::Used;
}
virtual void dec() override { sub(1); }
virtual void inc() override { add(1); }
virtual void set(uint64_t value) override {
data_.value_ = value;
data_.flags_ |= Flags::Used;
}
virtual void sub(uint64_t amount) override {
ASSERT(data_.value_ >= amount);
ASSERT(used());
data_.value_ -= amount;
}
virtual uint64_t value() const override { return data_.value_; }
bool used() const override { return data_.flags_ & Flags::Used; }

private:
StatData& data_;
StatDataAllocatorImpl<StatData>& alloc_;
};

TagProducerImpl::TagProducerImpl(const envoy::config::metrics::v2::StatsConfig& config) {
// To check name conflict.
reserveResources(config);
Expand Down Expand Up @@ -319,7 +215,142 @@ TagProducerImpl::addDefaultExtractors(const envoy::config::metrics::v2::StatsCon
return names;
}

// TODO(jmarantz): move this below HeapStatDataAllocator::alloc.
std::string Utility::sanitizeStatsName(const std::string& name) {
std::string stats_name = name;
std::replace(stats_name.begin(), stats_name.end(), ':', '_');
std::replace(stats_name.begin(), stats_name.end(), '\0', '_');
return stats_name;
}

/**
* Counter implementation that wraps a StatData. StatData must have data members:
* std::atomic<int64_t> value_;
* std::atomic<int64_t> pending_increment_;
* std::atomic<int16_t> flags_;
* std::atomic<int16_t> ref_count_;
*/
template <class StatData> class CounterImpl : public Counter, public MetricImpl {
public:
CounterImpl(StatData& data, StatDataAllocatorImpl<StatData>& alloc,
std::string&& tag_extracted_name, std::vector<Tag>&& tags)
: MetricImpl(data.name_, std::move(tag_extracted_name), std::move(tags)), data_(data),
alloc_(alloc) {}
~CounterImpl() { alloc_.free(data_); }

// Stats::Counter
void add(uint64_t amount) override {
data_.value_ += amount;
data_.pending_increment_ += amount;
data_.flags_ |= Flags::Used;
}

void inc() override { add(1); }
uint64_t latch() override { return data_.pending_increment_.exchange(0); }
void reset() override { data_.value_ = 0; }
bool used() const override { return data_.flags_ & Flags::Used; }
uint64_t value() const override { return data_.value_; }

private:
StatData& data_;
StatDataAllocatorImpl<StatData>& alloc_;
};

/**
* Gauge implementation that wraps a StatData.
*/
template <class StatData> class GaugeImpl : public Gauge, public MetricImpl {
public:
GaugeImpl(StatData& data, StatDataAllocatorImpl<StatData>& alloc,
std::string&& tag_extracted_name, std::vector<Tag>&& tags)
: MetricImpl(data.name_, std::move(tag_extracted_name), std::move(tags)), data_(data),
alloc_(alloc) {}
~GaugeImpl() { alloc_.free(data_); }

// Stats::Gauge
virtual void add(uint64_t amount) override {
data_.value_ += amount;
data_.flags_ |= Flags::Used;
}
virtual void dec() override { sub(1); }
virtual void inc() override { add(1); }
virtual void set(uint64_t value) override {
data_.value_ = value;
data_.flags_ |= Flags::Used;
}
virtual void sub(uint64_t amount) override {
ASSERT(data_.value_ >= amount);
ASSERT(used());
data_.value_ -= amount;
}
virtual uint64_t value() const override { return data_.value_; }
bool used() const override { return data_.flags_ & Flags::Used; }

private:
StatData& data_;
StatDataAllocatorImpl<StatData>& alloc_;
};

// Normally the compiler would do this, but because name_ is a flexible-array-length
// element, the compiler can't. RawStatData is put into an array in HotRestartImpl, so
// it's important that each element starts on the required alignment for the type.
uint64_t RawStatData::structSize(uint64_t name_size) {
return roundUpMultipleNaturalAlignment(sizeof(RawStatData) + name_size + 1);
}

uint64_t RawStatData::structSizeWithOptions(const StatsOptions& stats_options) {
return structSize(stats_options.maxNameLength());
}

void RawStatData::initialize(absl::string_view key, const StatsOptions& stats_options) {
ASSERT(!initialized());
ASSERT(key.size() <= stats_options.maxNameLength());
ref_count_ = 1;
memcpy(name_, key.data(), key.size());
name_[key.size()] = '\0';
}

HeapStatData::HeapStatData(absl::string_view key) : name_(key.data(), key.size()) {}

template <class StatData>
CounterSharedPtr StatDataAllocatorImpl<StatData>::makeCounter(absl::string_view name,
std::string&& tag_extracted_name,
std::vector<Tag>&& tags) {
StatData* data = alloc(name);
if (data == nullptr) {
return nullptr;
}
return std::make_shared<CounterImpl<StatData>>(*data, *this, std::move(tag_extracted_name),
std::move(tags));
}

template <class StatData>
GaugeSharedPtr StatDataAllocatorImpl<StatData>::makeGauge(absl::string_view name,
std::string&& tag_extracted_name,
std::vector<Tag>&& tags) {
StatData* data = alloc(name);
if (data == nullptr) {
return nullptr;
}
return std::make_shared<GaugeImpl<StatData>>(*data, *this, std::move(tag_extracted_name),
std::move(tags));
}

HeapStatData* HeapStatDataAllocator::alloc(absl::string_view name) {
// Any expected truncation of name is done at the callsite. No truncation is
// required to use this allocator.
auto data = std::make_unique<HeapStatData>(name);
Thread::ReleasableLockGuard lock(mutex_);
auto ret = stats_.insert(data.get());
HeapStatData* existing_data = *ret.first;
lock.release();

if (ret.second) {
return data.release();
}
++existing_data->ref_count_;
return existing_data;
}

void HeapStatDataAllocator::free(HeapStatData& data) {
ASSERT(data.ref_count_ > 0);
if (--data.ref_count_ > 0) {
Expand All @@ -335,14 +366,6 @@ void HeapStatDataAllocator::free(HeapStatData& data) {
delete &data;
}

void RawStatData::initialize(absl::string_view key, const StatsOptions& stats_options) {
ASSERT(!initialized());
ASSERT(key.size() <= stats_options.maxNameLength());
ref_count_ = 1;
memcpy(name_, key.data(), key.size());
name_[key.size()] = '\0';
}

HistogramStatisticsImpl::HistogramStatisticsImpl(const histogram_t* histogram_ptr)
: computed_quantiles_(supportedQuantiles().size(), 0.0) {
hist_approx_quantile(histogram_ptr, supportedQuantiles().data(), supportedQuantiles().size(),
Expand Down Expand Up @@ -401,28 +424,43 @@ void SourceImpl::clearCache() {
histograms_.reset();
}

template <class StatData>
CounterSharedPtr StatDataAllocatorImpl<StatData>::makeCounter(absl::string_view name,
std::string&& tag_extracted_name,
std::vector<Tag>&& tags) {
StatData* data = alloc(name);
if (data == nullptr) {
return nullptr;
IsolatedStoreImpl::IsolatedStoreImpl()
: counters_([this](const std::string& name) -> CounterSharedPtr {
std::string tag_extracted_name = name;
std::vector<Tag> tags;
return alloc_.makeCounter(name, std::move(tag_extracted_name), std::move(tags));
}),
gauges_([this](const std::string& name) -> GaugeSharedPtr {
std::string tag_extracted_name = name;
std::vector<Tag> tags;
return alloc_.makeGauge(name, std::move(tag_extracted_name), std::move(tags));
}),
histograms_([this](const std::string& name) -> HistogramSharedPtr {
return std::make_shared<HistogramImpl>(name, *this, std::string(name), std::vector<Tag>());
}) {}

struct IsolatedScopeImpl : public Scope {
IsolatedScopeImpl(IsolatedStoreImpl& parent, const std::string& prefix)
: parent_(parent), prefix_(Utility::sanitizeStatsName(prefix)) {}

// Stats::Scope
ScopePtr createScope(const std::string& name) override {
return ScopePtr{new IsolatedScopeImpl(parent_, prefix_ + name)};
}
return std::make_shared<CounterImpl<StatData>>(*data, *this, std::move(tag_extracted_name),
std::move(tags));
}

template <class StatData>
GaugeSharedPtr StatDataAllocatorImpl<StatData>::makeGauge(absl::string_view name,
std::string&& tag_extracted_name,
std::vector<Tag>&& tags) {
StatData* data = alloc(name);
if (data == nullptr) {
return nullptr;
void deliverHistogramToSinks(const Histogram&, uint64_t) override {}
Counter& counter(const std::string& name) override { return parent_.counter(prefix_ + name); }
Gauge& gauge(const std::string& name) override { return parent_.gauge(prefix_ + name); }
Histogram& histogram(const std::string& name) override {
return parent_.histogram(prefix_ + name);
}
return std::make_shared<GaugeImpl<StatData>>(*data, *this, std::move(tag_extracted_name),
std::move(tags));
const Stats::StatsOptions& statsOptions() const override { return parent_.statsOptions(); }

IsolatedStoreImpl& parent_;
const std::string prefix_;
};

ScopePtr IsolatedStoreImpl::createScope(const std::string& name) {
return ScopePtr{new IsolatedScopeImpl(*this, name)};
}

template class StatDataAllocatorImpl<HeapStatData>;
Expand Down
Loading