Skip to content

Commit c82c041

Browse files
committed
feat metrics: add UINVARIANT() on metrics registration & fix bugs
commit_hash:ed536be2effdaabe227756ce4e6fe229b309be6b
1 parent 89d8f7b commit c82c041

File tree

4 files changed

+45
-18
lines changed

4 files changed

+45
-18
lines changed

core/src/engine/task/task_processor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ TaskProcessor::TaskProcessor(TaskProcessorConfig config, std::shared_ptr<impl::T
133133
: task_queue_(MakeTaskQueue(config)),
134134
task_counter_(config.worker_threads),
135135
config_(config),
136-
pools_(std::move(pools)),
137136
plugin_manager_(*this, config.worker_threads),
137+
pools_(std::move(pools)),
138138
trace_plugin_(config.worker_threads)
139139
{
140140
utils::impl::FinishStaticRegistration();

core/src/engine/task/task_processor.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class TaskProcessor final {
137137
impl::TaskCounter task_counter_;
138138

139139
const TaskProcessorConfig config_;
140+
PluginManager plugin_manager_;
140141
const std::shared_ptr<impl::TaskProcessorPools> pools_;
141142
std::vector<std::thread> workers_;
142143
logging::LoggerPtr task_trace_logger_{nullptr};
@@ -154,7 +155,6 @@ class TaskProcessor final {
154155
std::unique_ptr<utils::statistics::ThreadPoolCpuStatsStorage> cpu_stats_storage_{nullptr};
155156
TaskProcessor* fs_task_processor_{nullptr};
156157

157-
PluginManager plugin_manager_;
158158
// TracePlugin must start before any task is created to account it
159159
TracePlugin trace_plugin_;
160160
};

core/src/utils/statistics/storage.cpp

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,48 @@ class FakeFormatBuilder final : public BaseFormatBuilder {
4343
void HandleMetric(std::string_view, LabelsSpan, const MetricValue&) override {}
4444
};
4545

46+
void WriteWithFakeFormat(impl::MetricsSource& source)
47+
{
48+
static constexpr std::string_view fake_prefix = "fake_prefix";
49+
if (source.writer) {
50+
FakeFormatBuilder builder;
51+
const Request request;
52+
impl::WriterState state{builder, request, {}, {}};
53+
auto writer = Writer{&state}[fake_prefix];
54+
source.writer(writer);
55+
}
56+
if (source.extender) {
57+
source.extender(StatisticsRequest{});
58+
}
59+
}
60+
61+
[[maybe_unused]] void CheckDataUsedByCallbackIsValidBeforeRegistering(impl::MetricsSource& source) noexcept {
62+
try {
63+
WriteWithFakeFormat(source);
64+
} catch (const std::exception& e) {
65+
utils::AbortWithStacktrace(fmt::format(
66+
"Unhandled exception while statistics holder {} is registering: {}",
67+
source.prefix_path,
68+
e.what()
69+
));
70+
}
71+
}
72+
4673
// During the `Entry::Unregister` call or destruction of `Entry`, all variables
4774
// used by the writer or extender callback must be valid (must not be
4875
// destroyed). A common cause of crashes in this place: there is no manual call
4976
// to `Unregister`. In this case, check the lifetime of the data used by the
5077
// callback.
5178
[[maybe_unused]] void CheckDataUsedByCallbackHasNotBeenDestroyedBeforeUnregistering(impl::MetricsSource& source
5279
) noexcept {
53-
static constexpr std::string_view fake_prefix = "fake_prefix";
5480
try {
55-
if (source.writer) {
56-
FakeFormatBuilder builder;
57-
const Request request;
58-
impl::WriterState state{builder, request, {}, {}};
59-
auto writer = Writer{&state}[fake_prefix];
60-
source.writer(writer);
61-
}
62-
if (source.extender) {
63-
source.extender(StatisticsRequest{});
64-
}
81+
WriteWithFakeFormat(source);
6582
} catch (const std::exception& e) {
66-
LOG_ERROR()
67-
<< "Unhandled exception while statistics holder " << source.prefix_path
68-
<< " is unregistering automatically: " << e.what();
83+
utils::AbortWithStacktrace(fmt::format(
84+
"Unhandled exception while statistics holder {} is unregistering automatically: {}",
85+
source.prefix_path,
86+
e.what()
87+
));
6988
}
7089
}
7190

@@ -185,6 +204,9 @@ Entry Storage::DoRegisterExtender(impl::MetricsSource&& source) {
185204
);
186205

187206
const std::lock_guard lock(mutex_);
207+
if constexpr (impl::kCheckSubscriptionUB) {
208+
CheckDataUsedByCallbackIsValidBeforeRegistering(source);
209+
}
188210
const auto res = metrics_sources_.insert(metrics_sources_.end(), std::move(source));
189211
return Entry(Entry::Impl{this, res});
190212
}

core/src/utils/statistics/writer_test.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,11 @@ UTEST(MetricsWriter, LabeledMultiple) {
365365
}
366366

367367
UTEST(MetricsWriter, CustomTypesOptimization) {
368+
if constexpr (utils::statistics::impl::kCheckSubscriptionUB) {
369+
return;
370+
}
371+
// Check for "not called" only if call on registration is not forced
372+
368373
Storage storage;
369374
auto holder = storage.RegisterWriter("skip", [](Writer& writer) {
370375
writer = MetricTypeThatMustBeSkipped{"at 'skip' path"};
@@ -432,7 +437,7 @@ UTEST(MetricsWriter, AutomaticUnsubscribingCheckWriterData) {
432437
}
433438

434439
if constexpr (utils::statistics::impl::kCheckSubscriptionUB) {
435-
EXPECT_EQ(counter, 1);
440+
EXPECT_EQ(counter, 3);
436441
} else {
437442
EXPECT_EQ(counter, 0);
438443
}
@@ -452,7 +457,7 @@ UTEST(MetricsWriter, AutomaticUnsubscribingCheckExtenderData) {
452457
}
453458

454459
if constexpr (utils::statistics::impl::kCheckSubscriptionUB) {
455-
EXPECT_EQ(counter, 1);
460+
EXPECT_EQ(counter, 3);
456461
} else {
457462
EXPECT_EQ(counter, 0);
458463
}

0 commit comments

Comments
 (0)