@@ -389,7 +389,9 @@ cb::engine_errc EventuallyPersistentEngine::get_prometheus_stats(
389389 const std::shared_ptr<ConnHandler>& tc) {
390390 ++aggregator.totalConns ;
391391 if (auto tp = std::dynamic_pointer_cast<DcpProducer>(tc); tp) {
392- tp->aggregateQueueStats (aggregator);
392+ // Do not use the potentially slower "accurate" items
393+ // remaining. MB-57400
394+ tp->aggregateQueueStats (aggregator, false );
393395 }
394396 });
395397 addAggregatedProducerStats (collector, aggregator);
@@ -402,7 +404,7 @@ cb::engine_errc EventuallyPersistentEngine::get_prometheus_stats(
402404 }
403405 // do dcp aggregated stats, using ":" as the separator to split
404406 // connection names to find the connection type.
405- if (status = doConnAggStatsInner (collector, " :" );
407+ if (status = doConnAggStatsInner (collector, " :" , false );
406408 status != cb::engine_errc::success) {
407409 return status;
408410 }
@@ -3916,7 +3918,7 @@ struct ConnStatBuilder {
39163918 tc->addStats (add_stat, cookie);
39173919 auto tp = std::dynamic_pointer_cast<DcpProducer>(tc);
39183920 if (tp) {
3919- tp->aggregateQueueStats (aggregator);
3921+ tp->aggregateQueueStats (aggregator, true );
39203922 }
39213923 }
39223924 }
@@ -3932,7 +3934,18 @@ struct ConnStatBuilder {
39323934};
39333935
39343936struct ConnAggStatBuilder {
3935- ConnAggStatBuilder (std::string_view sep) : sep(sep) {
3937+ /* *
3938+ * Construct with the separator and a configuration bool.
3939+ * @param sep The separator used for determining "type" of DCP connection
3940+ * by splitting the connection name with sep.
3941+ * @param alwaysUseAccurateItemsRemaining if true the aggregated stats will
3942+ * include an "accurate" items-remaining. If false only connections
3943+ * labelled as "replication" will use an accurate value. See MB-57400
3944+ */
3945+ ConnAggStatBuilder (std::string_view sep,
3946+ bool alwaysUseAccurateItemsRemaining)
3947+ : sep(sep),
3948+ alwaysUseAccurateItemsRemaining (alwaysUseAccurateItemsRemaining) {
39363949 }
39373950
39383951 /* *
@@ -3950,22 +3963,23 @@ struct ConnAggStatBuilder {
39503963 * returns nullptr.
39513964 *
39523965 * @param tc connection
3953- * @return counter for the given connection, or nullptr
3966+ * @return pair of counter for the given connection, or nullptr and true
3967+ * if the connection is considered a replication stream
39543968 */
3955- ConnCounter* getCounterForConnType (std::string_view name) {
3969+ std::pair< ConnCounter*, bool > getCounterForConnType (std::string_view name) {
39563970 // strip everything upto and including the first colon,
39573971 // e.g., "eq_dcpq:"
39583972 size_t pos1 = name.find (' :' );
39593973 if (pos1 == std::string_view::npos) {
3960- return nullptr ;
3974+ return { nullptr , false } ;
39613975 }
39623976
39633977 name.remove_prefix (pos1 + 1 );
39643978
39653979 // find the given separator
39663980 size_t pos2 = name.find (sep);
39673981 if (pos2 == std::string_view::npos) {
3968- return nullptr ;
3982+ return { nullptr , false } ;
39693983 }
39703984
39713985 // extract upto given separator e.g.,
@@ -3976,14 +3990,18 @@ struct ConnAggStatBuilder {
39763990 // prefix is "replication"
39773991 std::string prefix (name.substr (0 , pos2));
39783992
3979- return &counters[prefix];
3993+ // class is created with the itemsRemaining "policy" - which if not true
3994+ // replication will always use the accurate items remaining - all
3995+ // other connection types use a faster estimate.
3996+ return {&counters[prefix],
3997+ alwaysUseAccurateItemsRemaining || prefix == " replication" };
39803998 }
39813999
3982- void aggregate (ConnHandler& conn, ConnCounter* tc) {
4000+ void aggregate (ConnHandler& conn, ConnCounter* tc, bool isReplication ) {
39834001 ConnCounter counter;
39844002 ++counter.totalConns ;
39854003
3986- conn.aggregateQueueStats (counter);
4004+ conn.aggregateQueueStats (counter, isReplication );
39874005
39884006 ConnCounter& total = getTotalCounter ();
39894007 total += counter;
@@ -3999,8 +4017,8 @@ struct ConnAggStatBuilder {
39994017
40004018 void operator ()(std::shared_ptr<ConnHandler> tc) {
40014019 if (tc) {
4002- ConnCounter* aggregator = getCounterForConnType (tc->getName ());
4003- aggregate (*tc, aggregator);
4020+ auto aggregator = getCounterForConnType (tc->getName ());
4021+ aggregate (*tc, aggregator. first , aggregator. second );
40044022 }
40054023 }
40064024
@@ -4010,6 +4028,7 @@ struct ConnAggStatBuilder {
40104028
40114029 std::map<std::string, ConnCounter> counters;
40124030 std::string_view sep;
4031+ const bool alwaysUseAccurateItemsRemaining{false };
40134032};
40144033
40154034// / @endcond
@@ -4102,8 +4121,8 @@ cb::engine_errc EventuallyPersistentEngine::doConnAggStats(
41024121 // write them as responses (which would be racy).
41034122 // a later call to maybeWriteResponse will do that.
41044123 CBStatCollector col (deferredAddStat, cookie);
4105- ep->doConnAggStatsInner (col. forBucket (ep-> getName ()),
4106- separator);
4124+ ep->doConnAggStatsInner (
4125+ col. forBucket (ep-> getName ()), separator, true );
41074126 return cb::engine_errc::success;
41084127 });
41094128 ExecutorPool::get ()->schedule (task);
@@ -4115,13 +4134,15 @@ cb::engine_errc EventuallyPersistentEngine::doConnAggStats(
41154134}
41164135
41174136cb::engine_errc EventuallyPersistentEngine::doConnAggStatsInner (
4118- const BucketStatCollector& collector, std::string_view sep) {
4137+ const BucketStatCollector& collector,
4138+ std::string_view sep,
4139+ bool cmdStat) {
41194140 // The separator is, in all current usage, ":" so the length will
41204141 // normally be 1
41214142 const size_t max_sep_len (8 );
41224143 sep = sep.substr (0 , max_sep_len);
41234144
4124- ConnAggStatBuilder visitor (sep);
4145+ ConnAggStatBuilder visitor (sep, cmdStat );
41254146 dcpConnMap_->each (visitor);
41264147
41274148 for (const auto & [connType, counter] : visitor.getCounters ()) {
0 commit comments