Skip to content

Commit 49e1028

Browse files
committed
fix. stats manager may cause crash when stats with new labels.
1 parent cdeab59 commit 49e1028

File tree

2 files changed

+75
-23
lines changed

2 files changed

+75
-23
lines changed

src/common/stats/StatsManager.cpp

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -177,18 +177,24 @@ CounterId StatsManager::counterWithLabels(const CounterId& id,
177177
}
178178
newIndex.back() = '}';
179179

180-
auto it = sm.nameMap_.find(newIndex);
181-
// Get the counter if it already exists
182-
if (it != sm.nameMap_.end()) {
183-
return it->second.id_;
184-
}
185-
186-
// Register a new counter if it doesn't exist
187-
auto it2 = sm.nameMap_.find(index);
188-
DCHECK(it2 != sm.nameMap_.end());
189-
auto& methods = it2->second.methods_;
190-
191-
return registerStats(newIndex, methods);
180+
std::vector<StatsMethod> methods;
181+
{
182+
folly::RWSpinLock::ReadHolder rh(sm.nameMapLock_);
183+
// Check if the counter already exists
184+
auto it = sm.nameMap_.find(newIndex);
185+
if (it != sm.nameMap_.end()) {
186+
// fast path if the counter already exists
187+
return it->second.id_;
188+
}
189+
190+
// Register a new counter if it doesn't exist
191+
// Fetch the counter indexed by the parent index and get the methods
192+
auto it2 = sm.nameMap_.find(index);
193+
DCHECK(it2 != sm.nameMap_.end());
194+
methods = it2->second.methods_;
195+
}
196+
197+
return registerStats(newIndex, *methods);
192198
}
193199

194200
// static
@@ -205,19 +211,35 @@ CounterId StatsManager::histoWithLabels(const CounterId& id, const std::vector<L
205211
newIndex.append(k).append("=").append(v).append(",");
206212
}
207213
newIndex.back() = '}';
208-
auto it = sm.nameMap_.find(newIndex);
209-
// Get the counter if it already exists
210-
if (it != sm.nameMap_.end()) {
211-
return it->second.id_;
212-
}
213214

214-
auto it2 = sm.nameMap_.find(index);
215-
DCHECK(it2 != sm.nameMap_.end());
216-
auto& methods = it2->second.methods_;
217-
auto& percentiles = it2->second.percentiles_;
215+
std::vector<StatsMethod> methods;
216+
std::vector<std::pair<std::string, double>> percentiles;
217+
StatsManager::VT bucketSize, min, max;
218+
{
219+
folly::RWSpinLock::ReadHolder rh(sm.nameMapLock_);
220+
// Check if the counter already exists
221+
auto it = sm.nameMap_.find(newIndex);
222+
if (it != sm.nameMap_.end()) {
223+
// fast path if the counter already exists
224+
return it->second.id_;
225+
}
226+
// Register a new counter if it doesn't exist
227+
// Fetch the counter indexed by the parent index and get the methods
228+
auto it2 = sm.nameMap_.find(index);
229+
DCHECK(it2 != sm.nameMap_.end());
230+
methods = it2->second.methods_;
231+
percentiles = it2->second.percentiles_;
232+
bucketSize = it2->second.bucketSize_;
233+
min = it2->second.min_;
234+
max = it2->second.max_;
235+
}
218236

219-
return registerHisto(
220-
newIndex, it2->second.bucketSize_, it2->second.min_, it2->second.max_, methods, percentiles);
237+
return registerHisto(/* counterName */ newIndex,
238+
/* bucketSize */ bucketSize,
239+
/* min */ min,
240+
/* max */ max,
241+
/* methods */ *methods,
242+
/* percentiles */ *percentiles);
221243
}
222244

223245
// static

src/common/stats/test/StatsManagerTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,36 @@ TEST(StatsManager, ReadAllTest) {
163163
EXPECT_FALSE(counterExists(stats2, "stat04{space=test}.p95.5", val));
164164
}
165165

166+
TEST(StatsManager, ConcurrentCountWithLabelTest) {
167+
auto statId = StatsManager::registerStats("stat06", "RATE, sum");
168+
std::vector<std::thread> threads;
169+
for (int i = 0; i < 257; i++) {
170+
std::string spaceName = folly::stringPrintf("space%d", i);
171+
threads.emplace_back([&statId, &spaceName]() {
172+
auto counterId = StatsManager::counterWithLabels(statId, {{"space", spaceName}});
173+
});
174+
}
175+
176+
for (auto& t : threads) {
177+
t.join();
178+
}
179+
}
180+
181+
TEST(StatsManager, ConcurrentHistoWithLabelTest) {
182+
auto statId = StatsManager::registerHisto("stat07", 1, 1, 100, "sum, p95, p99");
183+
std::vector<std::thread> threads;
184+
for (int i = 0; i < 257; i++) {
185+
std::string spaceName = folly::stringPrintf("space%d", i);
186+
threads.emplace_back([&statId, &spaceName]() {
187+
auto histoId = StatsManager::histoWithLabels(statId, {{"space", spaceName}});
188+
});
189+
}
190+
191+
for (auto& t : threads) {
192+
t.join();
193+
}
194+
}
195+
166196
} // namespace stats
167197
} // namespace nebula
168198

0 commit comments

Comments
 (0)