-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
stats: add built-in log linear histogram support #2932
Changes from 3 commits
f0a7faa
1a35b0e
5b66b74
8052ae7
5d30b85
a0bf03c
dede1fd
e744253
0aeac15
c200974
dd79e35
9dcddf6
5e8169a
f35083c
08cc211
a107b0f
dadba03
e41d7ef
9da426e
92620e5
6e6253a
6ca87c4
fa8f646
2b5772f
1032ffc
8266868
a041a3e
c9fef4b
29646d0
df348b2
68039f2
1b75b93
d5d4125
16003e7
05d00a2
9189b9e
1837956
8b1c7ab
2894da8
1e1f494
5ae99d3
7d3844e
5ccad60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
cc_library( | ||
name = "libcircllhist", | ||
srcs = ["src/circllhist.c"], | ||
hdrs = [ | ||
"src/circllhist.h", | ||
"src/circllhist_config.h", # Generated. | ||
], | ||
includes = ["src"], | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
genrule( | ||
name = "circllhist_config", | ||
srcs = ["src/circllhist_config.h.in"], | ||
outs = ["src/circllhist_config.h"], | ||
cmd = "cp $< $@", | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -263,6 +263,11 @@ class Store : public Scope { | |
* @return a list of all known gauges. | ||
*/ | ||
virtual std::list<GaugeSharedPtr> gauges() const PURE; | ||
|
||
virtual std::list<HistogramSharedPtr> histograms() const { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same, PURE, every store should implement. |
||
std::list<HistogramSharedPtr> empty_list; | ||
return empty_list; | ||
} | ||
}; | ||
|
||
typedef std::unique_ptr<Store> StorePtr; | ||
|
@@ -294,6 +299,8 @@ class StoreRoot : public Store { | |
* down. | ||
*/ | ||
virtual void shutdownThreading() PURE; | ||
|
||
virtual void mergeHistograms() {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same: please also add doc comments for all interface functions (above also). |
||
}; | ||
|
||
typedef std::unique_ptr<StoreRoot> StoreRootPtr; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,10 @@ | |
|
||
#include "absl/strings/string_view.h" | ||
|
||
extern "C" { | ||
#include <circllhist.h> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #include "circlehist.h" <> should be used for system includes (e.g. included with the OS or compiler). Also I would've thought this should be in a subdir. |
||
} | ||
|
||
namespace Envoy { | ||
namespace Stats { | ||
|
||
|
@@ -369,6 +373,128 @@ class HistogramImpl : public Histogram, public MetricImpl { | |
Store& parent_; | ||
}; | ||
|
||
/** | ||
* Structure to hold statistical data of histogram. | ||
*/ | ||
struct HistogramStatistics { | ||
public: | ||
HistogramStatistics(histogram_t* histogram_ptr) { | ||
double quantile_in[] = {0, 0.25, 0.5, 0.75, 0.90, 0.95, 0.99, 0.999, 1}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. factor out this constant so it only appears once. I see it also in grpc_metrics_service_impl.h:149 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i am not able to make it const - because of my c++ knowledge levels :-). But made it class variable and used it every where. |
||
hist_approx_quantile(histogram_ptr, quantile_in, ARRAY_SIZE(quantile_in), quantile_out_); | ||
} | ||
|
||
std::string summary() const { | ||
return fmt::format("P0: {} , P25: {}, P50: {}, P75: {}, P90: {}, P95: {}, P99: {}, P100: {}", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WDYT of constructing this by looping over the quantiles_in_ and quantiles_out_ vectors, so they'll never get out of sink. In fact it looks like they are out of sink now as you have a .999 in the quantiles_in_ initializer above; only 8 values in your format string and 9 args below. Easy to miss. Let's avoid that by constructing this from the source of truth. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
quantile_out_[0], quantile_out_[1], quantile_out_[2], quantile_out_[3], | ||
quantile_out_[4], quantile_out_[5], quantile_out_[6], quantile_out_[7], | ||
quantile_out_[8]); | ||
} | ||
|
||
private: | ||
double quantile_out_[9]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. double quantile_out_[ARRAY_SIZE(quantile_in)]; |
||
}; | ||
|
||
/** | ||
* Log Linear Histogram implementation per thread. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we move ThreadLocalHistogramImpl and HistogramParentImpl directly into thread_local_store. We are going to have to deal with some locking issues and I would like things to be more explicitly coupled. We can break it apart later if necessary. |
||
*/ | ||
class ThreadLocalHistogramImpl : public Histogram, public MetricImpl { | ||
public: | ||
ThreadLocalHistogramImpl(const std::string& name, Store& parent, std::string&& tag_extracted_name, | ||
std::vector<Tag>&& tags) | ||
: MetricImpl(name, std::move(tag_extracted_name), std::move(tags)), parent_(parent) { | ||
histograms_[0] = hist_alloc(); | ||
histograms_[1] = hist_alloc(); | ||
current_active_ = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. initialize this and next line in initializer list |
||
} | ||
|
||
~ThreadLocalHistogramImpl() { | ||
hist_free(histograms_[0]); | ||
hist_free(histograms_[1]); | ||
} | ||
// Stats::Histogram | ||
void recordValue(uint64_t value) override { | ||
hist_insert_intscale(histograms_[current_active_], value, 0, 1); | ||
parent_.deliverHistogramToSinks(*this, value); | ||
} | ||
|
||
void beginMerge() { | ||
if (current_active_ == 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: current_active_ = 1 - current_active_; |
||
current_active_ = 1; | ||
} else { | ||
current_active_ = 0; | ||
} | ||
} | ||
|
||
void merge(histogram_t* target) { | ||
histogram_t* hist_array[1]; | ||
if (current_active_ == 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: hist_array[0] = histograms_[1 - current_active_]; |
||
hist_array[0] = histograms_[1]; | ||
} else { | ||
hist_array[0] = histograms_[0]; | ||
} | ||
hist_accumulate(target, hist_array, 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/1/ARRAY_SIZE(hist_array)/ |
||
hist_clear(hist_array[0]); | ||
} | ||
|
||
Store& parent_; | ||
int current_active_; | ||
histogram_t* histograms_[2]; | ||
}; | ||
|
||
typedef std::shared_ptr<ThreadLocalHistogramImpl> TlsHistogramSharedPtr; | ||
|
||
/** | ||
* Log Linear Histogram implementation that is stored in the main thread. | ||
*/ | ||
class HistogramParentImpl : public Histogram, public MetricImpl { | ||
public: | ||
HistogramParentImpl(const std::string& name, Store& parent, std::string&& tag_extracted_name, | ||
std::vector<Tag>&& tags) | ||
: MetricImpl(name, std::move(tag_extracted_name), std::move(tags)), parent_(parent) { | ||
interval_histogram_ = hist_alloc(); | ||
cumulative_histogram_ = hist_alloc(); | ||
} | ||
|
||
~HistogramParentImpl() { | ||
hist_free(interval_histogram_); | ||
hist_free(cumulative_histogram_); | ||
} | ||
|
||
// Stats::Histogram | ||
void recordValue(uint64_t) override {} | ||
|
||
void addTlsHistogram(HistogramSharedPtr hist_ptr) { tls_histograms_.emplace_back(hist_ptr); } | ||
|
||
void merge() { | ||
hist_clear(interval_histogram_); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you comment about the threading model here? or maybe just point to Matt's design in github? |
||
for (auto tls_histogram : tls_histograms_) { | ||
TlsHistogramSharedPtr tls_histogram_ptr = | ||
std::dynamic_pointer_cast<ThreadLocalHistogramImpl>(tls_histogram); | ||
tls_histogram_ptr->merge(interval_histogram_); | ||
} | ||
histogram_t* hist_array[1]; | ||
hist_array[0] = interval_histogram_; | ||
hist_accumulate(cumulative_histogram_, hist_array, 1); | ||
} | ||
|
||
HistogramStatistics getIntervalHistogramStatistics() { | ||
HistogramStatistics interval_histogram(interval_histogram_); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggest: return HistogramStatistics(interval_histogram_); |
||
return interval_histogram; | ||
} | ||
|
||
HistogramStatistics getCumulativieHistogramStatistics() { | ||
HistogramStatistics cumulative_histogram(cumulative_histogram_); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. |
||
return cumulative_histogram_; | ||
} | ||
|
||
Store& parent_; | ||
std::list<HistogramSharedPtr> tls_histograms_; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we use the more specific type here to avoid dynamic_cast? |
||
histogram_t* interval_histogram_; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think in looking at this now I would make HistogramStatistics an interface, then where you need it, have an impl that wraps the circl implementation, which you can then return via const reference. |
||
histogram_t* cumulative_histogram_; | ||
}; | ||
|
||
typedef std::shared_ptr<HistogramParentImpl> ParentHistogramSharedPtr; | ||
|
||
/** | ||
* Implementation of RawStatDataAllocator that just allocates a new structure in memory and returns | ||
* it. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,22 @@ std::list<GaugeSharedPtr> ThreadLocalStoreImpl::gauges() const { | |
return ret; | ||
} | ||
|
||
std::list<HistogramSharedPtr> ThreadLocalStoreImpl::histograms() const { | ||
// Handle de-dup due to overlapping scopes. | ||
std::list<HistogramSharedPtr> ret; | ||
std::unordered_set<std::string> names; | ||
std::unique_lock<std::mutex> lock(lock_); | ||
for (ScopeImpl* scope : scopes_) { | ||
for (auto histogram : scope->central_cache_.histograms_) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The style-guide (https://google.github.io/styleguide/cppguide.html#auto) leaves some room for interpretation, but my reading is that in this case and a few others in this PR, you should use explicit types. If you were using iterator objects, those are good candidates for 'auto' because their types are fairly obvious and not necessarily important to spell out. e..g.
or
But it's possible there's an established style here I'm going against the grain in suggesting. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am changing it like this to be type explicit. Is that fine?
|
||
if (names.insert(histogram.first).second) { | ||
ret.push_back(histogram.second); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably worth a note here that the histograms will come back in arbitrary order. suggestion: return a vector rather than a list, and build that vector after accumulating the set, so that: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jmarantz have not addressed this yet. will address in next round. :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realize on re-read that there's an established pattern of using lists rather than for returning collections of stats. @mattklein123 -- I'm curious why that choice? But for this PR I retract this suggestion -- it probably doesn't save that much to release the lock earlier. I would like to see some comments as to why this de-duping is necessary though; that seems like something must have gone wrong upstream for it to be needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't remember why this was a list. I think this was historical. Free free to return a vector if you want to change the various usages. re: The de-dup, that is required due to the threaded store uses scopes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we incorporate the scopes into the histogram names somehow, so we have distinct ones for each scope? It seems like just dropping them would lose data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm yes, this is a problem for histograms which don't use shared mem backing store. It's not an issue for counters/gauges. Good catch. This will need to be fixed somehow. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool... @ramaraochavali you can maybe leave a TODO here, and maybe even a warning log that we are dropping content? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jmarantz I have added a todo and not changing the return type now based on your comment above about "I retract this suggestion". Is that fine? |
||
} | ||
} | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
void ThreadLocalStoreImpl::initializeThreading(Event::Dispatcher& main_thread_dispatcher, | ||
ThreadLocal::Instance& tls) { | ||
main_thread_dispatcher_ = &main_thread_dispatcher; | ||
|
@@ -75,6 +91,36 @@ void ThreadLocalStoreImpl::shutdownThreading() { | |
shutting_down_ = true; | ||
} | ||
|
||
void ThreadLocalStoreImpl::mergeHistograms() { | ||
if (!shutting_down_) { | ||
std::unique_lock<std::mutex> lock(lock_); | ||
// TODO: Wait till all threads have been checked-in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mattklein123 I need your help here. How do I wait till all worker threads have finished? Is there a standard pattern in c++/envoy code here that I can use? Tried to look at latch/barrier support but could not find such thing. This is the only thing pending from basic implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In a perfect world you could add barrier/notify functionality into the TLS itself, e.g., There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added the method in TLS system. |
||
tls_->runOnAllThreads([this]() -> void { | ||
for (ScopeImpl* scope : scopes_) { | ||
for (auto histogram : tls_->getTyped<TlsCache>().scope_cache_[scope].histograms_) { | ||
TlsHistogramSharedPtr tls_histogram_ptr = | ||
std::dynamic_pointer_cast<ThreadLocalHistogramImpl>(histogram.second); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove dynamic_cast (by storing impls if needed). I will stop commenting but basically the change should have no dynamic_casts. |
||
tls_histogram_ptr->beginMerge(); | ||
} | ||
} | ||
}); | ||
if (main_thread_dispatcher_) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think main_thread_dispatcher_ must be non-nullptr here. I would skip this check? Obviously this also needs to get moved inside the run on all threads lambda above, see my comment above. |
||
main_thread_dispatcher_->post([this]() -> void { mergeInternal(); }); | ||
} | ||
} | ||
} | ||
|
||
void ThreadLocalStoreImpl::mergeInternal() { | ||
std::unique_lock<std::mutex> lock(lock_); | ||
for (ScopeImpl* scope : scopes_) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use |
||
for (auto histogram : scope->central_cache_.histograms_) { | ||
ParentHistogramSharedPtr parent_hist_ptr = | ||
std::dynamic_pointer_cast<HistogramParentImpl>(histogram.second); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to remove all the dynamic casts here, I would change the map to store impls so you can use them locally. |
||
parent_hist_ptr->merge(); | ||
} | ||
} | ||
} | ||
|
||
void ThreadLocalStoreImpl::releaseScopeCrossThread(ScopeImpl* scope) { | ||
std::unique_lock<std::mutex> lock(lock_); | ||
ASSERT(scopes_.count(scope) == 1); | ||
|
@@ -215,18 +261,22 @@ Histogram& ThreadLocalStoreImpl::ScopeImpl::histogram(const std::string& name) { | |
|
||
std::unique_lock<std::mutex> lock(parent_.lock_); | ||
HistogramSharedPtr& central_ref = central_cache_.histograms_[final_name]; | ||
|
||
std::vector<Tag> tags; | ||
std::string tag_extracted_name = parent_.getTagsForName(final_name, tags); | ||
if (!central_ref) { | ||
std::vector<Tag> tags; | ||
std::string tag_extracted_name = parent_.getTagsForName(final_name, tags); | ||
central_ref.reset( | ||
new HistogramImpl(final_name, parent_, std::move(tag_extracted_name), std::move(tags))); | ||
central_ref.reset(new HistogramParentImpl(final_name, parent_, std::move(tag_extracted_name), | ||
std::move(tags))); | ||
} | ||
HistogramSharedPtr hist_tls_ptr; | ||
hist_tls_ptr.reset(new ThreadLocalHistogramImpl(final_name, parent_, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: merge into previous line, or do directly in the context of addTlsHistogram() |
||
std::move(tag_extracted_name), std::move(tags))); | ||
dynamic_cast<HistogramParentImpl&>(*central_ref).addTlsHistogram(hist_tls_ptr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no dynamic cast. You can store a local ref/pointer if needed to have access to the impl, or just the local map to storing impls. |
||
|
||
if (tls_ref) { | ||
*tls_ref = central_ref; | ||
*tls_ref = hist_tls_ptr; | ||
} | ||
|
||
return *central_ref; | ||
return *hist_tls_ptr; | ||
} | ||
|
||
} // namespace Stats | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,6 +64,7 @@ class ThreadLocalStoreImpl : public StoreRoot { | |
// Stats::Store | ||
std::list<CounterSharedPtr> counters() const override; | ||
std::list<GaugeSharedPtr> gauges() const override; | ||
std::list<HistogramSharedPtr> histograms() const override; | ||
|
||
// Stats::StoreRoot | ||
void addSink(Sink& sink) override { timer_sinks_.push_back(sink); } | ||
|
@@ -74,6 +75,10 @@ class ThreadLocalStoreImpl : public StoreRoot { | |
ThreadLocal::Instance& tls) override; | ||
void shutdownThreading() override; | ||
|
||
void mergeHistograms() override; | ||
|
||
void mergeInternal(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. private |
||
|
||
private: | ||
struct TlsCacheEntry { | ||
std::unordered_map<std::string, CounterSharedPtr> counters_; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ | |
#include "common/network/listen_socket_impl.h" | ||
#include "common/profiler/profiler.h" | ||
#include "common/router/config_impl.h" | ||
#include "common/stats/stats_impl.h" | ||
#include "common/upstream/host_utility.h" | ||
|
||
#include "absl/strings/str_replace.h" | ||
|
@@ -392,6 +393,7 @@ Http::Code AdminImpl::handlerStats(absl::string_view url, Http::HeaderMap& respo | |
Http::Code rc = Http::Code::OK; | ||
const Http::Utility::QueryParams params = Http::Utility::parseQueryString(url); | ||
std::map<std::string, uint64_t> all_stats; | ||
std::map<std::string, std::string> all_histograms; | ||
for (const Stats::CounterSharedPtr& counter : server_.stats().counters()) { | ||
all_stats.emplace(counter->name(), counter->value()); | ||
} | ||
|
@@ -400,11 +402,24 @@ Http::Code AdminImpl::handlerStats(absl::string_view url, Http::HeaderMap& respo | |
all_stats.emplace(gauge->name(), gauge->value()); | ||
} | ||
|
||
for (const Stats::HistogramSharedPtr& histogram : server_.stats().histograms()) { | ||
Stats::ParentHistogramSharedPtr parent_hist_ptr = | ||
std::dynamic_pointer_cast<Stats::HistogramParentImpl>(histogram); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no dynamic cast |
||
all_histograms.emplace( | ||
parent_hist_ptr->name(), | ||
fmt::format("\n \t Interval: {} \n \t Cumulative: {}", | ||
parent_hist_ptr->getIntervalHistogramStatistics().summary(), | ||
parent_hist_ptr->getCumulativieHistogramStatistics().summary())); | ||
} | ||
|
||
if (params.size() == 0) { | ||
// No Arguments so use the standard. | ||
for (auto stat : all_stats) { | ||
response.add(fmt::format("{}: {}\n", stat.first, stat.second)); | ||
} | ||
for (auto histogram : all_histograms) { | ||
response.add(fmt::format("{}: {}\n", histogram.first, histogram.second)); | ||
} | ||
} else { | ||
const std::string format_key = params.begin()->first; | ||
const std::string format_value = params.begin()->second; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -139,6 +139,7 @@ void InstanceImpl::flushStats() { | |
server_stats_->days_until_first_cert_expiring_.set( | ||
sslContextManager().daysUntilFirstCertExpires()); | ||
|
||
stats_store_.mergeHistograms(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we do this, the merge will essentially always be one interval behind the flush interval. Is this what we want? Do we want to wait into the merge is complete? If so, my thinking was to have mergeHistograms() take a lambda which would fire when the merge is complete, and then the flush would complete. Also, on this topic, for thought: I do wonder if the histogram merge interval should be separately configurable from the main stat flush interval. (E.g., let's say you wanted to flush stats/gauges every 500ms, you might want to wait longer to get more histogram data per interval). I would put in a TODO to consider this in the future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did not get the first part. Since we block till all tls histograms are merged then main merge goes in sequentially - is the lambda still required? I may be missing some thing |
||
InstanceUtil::flushCountersAndGaugesToSinks(config_->statsSinks(), stats_store_); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you rename this function to something more appropriate? |
||
stat_flush_timer_->enableTimer(config_->statsFlushInterval()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we follow up on @jmillikin-stripe comment here? It does seem weird that the generated header is just being copied. Can you add a comment as to why this is OK if it is? cc @postwait
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The _config.h.in is an autoconf input template. It is not safe to copy it on all platforms. There is a
in the circllhist.c file that needs that that conditionally set depending on system headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@postwait thanks. What is your suggestion here? Should I copy based on platform? or which platforms it is good to copy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
libcircllhist (like many open source projects) is auto-tools based. When you build it, it will build-time detect which features are available on your platform and act on that. I don't know how to do the same thing in cmake. I am pretty sure that HAVE_ALLOCA_H is the only important thing in that header though -- so if you can get cmake to provide that, you're set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this, it is only alloca() that is a problem. I've opened a PR on libcircllhist to resolve this. It should be possible shortly to just ignore that header completely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@postwait thank you so much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@postwait Awesome. Thanks. I got the new version and removed the genRule and it works.