Skip to content

Commit 22ef726

Browse files
authored
Merge pull request #8680 from The-OpenROAD-Project-staging/secure-add-warning-metrics
Added new metrics for warnings.
2 parents 69a7c63 + d04cca3 commit 22ef726

5 files changed

Lines changed: 115 additions & 0 deletions

File tree

src/utl/include/utl/Logger.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ class Logger
279279
const Args&... args)
280280
{
281281
assert(id >= 0 && id <= max_message_id);
282+
message_levels_[tool][id].store(level, std::memory_order_relaxed);
282283
auto& counter = message_counters_[tool][id];
283284
auto count = counter++;
284285
if (count < max_message_print) {
@@ -319,6 +320,9 @@ class Logger
319320

320321
void flushMetrics();
321322
void finalizeMetrics();
323+
// Add new metrics for non-zero warnings. It also counts the number of
324+
// unique warning types.
325+
void addWarningMetrics();
322326

323327
void setRedirectSink(std::ostream& sink_stream, bool keep_sinks = false);
324328
void restoreFromRedirect();
@@ -359,6 +363,9 @@ class Logger
359363
// from multiple threads without locks.
360364
using MessageCounter = std::array<std::atomic_int16_t, max_message_id + 1>;
361365
std::array<MessageCounter, ToolId::SIZE> message_counters_;
366+
using MessageLevel
367+
= std::array<std::atomic<spdlog::level::level_enum>, max_message_id + 1>;
368+
std::array<MessageLevel, ToolId::SIZE> message_levels_;
362369
std::array<DebugGroups, ToolId::SIZE> debug_group_level_;
363370
bool debug_on_{false};
364371
std::atomic_int warning_count_{0};

src/utl/src/Logger.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "utl/Logger.h"
55

66
#include <algorithm>
7+
#include <atomic>
78
#include <cstdint>
89
#include <cstring>
910
#include <fstream>
@@ -21,6 +22,7 @@
2122
#else
2223
#include "spdlog/pattern_formatter.h"
2324
#endif
25+
#include "spdlog/common.h"
2426
#include "spdlog/sinks/basic_file_sink.h"
2527
#include "spdlog/sinks/ostream_sink.h"
2628
#include "spdlog/sinks/stdout_color_sinks.h"
@@ -58,6 +60,12 @@ Logger::Logger(const char* log_filename, const char* metrics_filename)
5860
}
5961
}
6062

63+
for (auto& levels : message_levels_) {
64+
for (auto& level : levels) {
65+
level.store(spdlog::level::off, std::memory_order_relaxed);
66+
}
67+
}
68+
6169
prometheus_registry_ = std::make_shared<PrometheusRegistry>();
6270
}
6371

@@ -178,11 +186,34 @@ void Logger::flushMetrics()
178186
}
179187
}
180188

189+
void Logger::addWarningMetrics()
190+
{
191+
// Add metrics for non-zero warnings
192+
int warning_type_cnt = 0;
193+
for (int i = 0; i < ToolId::SIZE; ++i) {
194+
for (int j = 0; j <= max_message_id; ++j) {
195+
if (message_counters_[i][j] > 0
196+
&& message_levels_[i][j] == spdlog::level::warn) {
197+
warning_type_cnt++;
198+
log_metric(
199+
// NOLINTNEXTLINE(misc-include-cleaner)
200+
fmt::format("flow__warnings__count:{}-{}", tool_names_[i], j),
201+
std::to_string(message_counters_[i][j]));
202+
}
203+
}
204+
}
205+
206+
// Add a metric to report the number of unique warning types
207+
log_metric("flow__warnings__type_count", std::to_string(warning_type_cnt));
208+
}
209+
181210
void Logger::finalizeMetrics()
182211
{
183212
log_metric("flow__warnings__count", std::to_string(warning_count_));
184213
log_metric("flow__errors__count", std::to_string(error_count_));
185214

215+
addWarningMetrics();
216+
186217
for (MetricsPolicy policy : metrics_policies_) {
187218
policy.applyPolicy(metrics_entries_);
188219
}

src/utl/test/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,15 @@ cc_test(
8686
"@googletest//:gtest_main",
8787
],
8888
)
89+
90+
cc_test(
91+
name = "TestMetrics",
92+
srcs = [
93+
"cpp/TestMetrics.cpp",
94+
],
95+
deps = [
96+
"//src/utl",
97+
"@googletest//:gtest",
98+
"@googletest//:gtest_main",
99+
],
100+
)

src/utl/test/cpp/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,16 @@ gtest_discover_tests(TestCFileUtils
1818
add_dependencies(build_and_test
1919
TestCFileUtils
2020
)
21+
22+
23+
add_executable(TestMetrics TestMetrics.cpp)
24+
25+
target_link_libraries(TestMetrics ${TEST_LIBS})
26+
27+
gtest_discover_tests(TestMetrics
28+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
29+
)
30+
31+
add_dependencies(build_and_test
32+
TestMetrics
33+
)

src/utl/test/cpp/TestMetrics.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2024, The OpenROAD Authors
3+
4+
#include <cstdio>
5+
#include <fstream>
6+
#include <iterator>
7+
#include <string>
8+
9+
#include "gtest/gtest.h"
10+
#include "utl/Logger.h"
11+
12+
namespace utl {
13+
14+
TEST(Utl, WarningMetrics)
15+
{
16+
// ARRANGE
17+
std::string metrics_filename = "test_metrics_warning_metrics.rpt";
18+
// The logger must be scoped to trigger the destructor which writes the
19+
// metrics
20+
{
21+
utl::Logger logger;
22+
logger.addMetricsSink(metrics_filename.c_str());
23+
24+
// ACTION
25+
for (int i = 0; i < 10; i++) {
26+
logger.warn(utl::UTL, 20, "Test warning UTL-20.");
27+
}
28+
logger.warn(utl::UTL, 21, "Another test warning UTL-21.");
29+
}
30+
31+
// ASSERT
32+
std::ifstream metrics_file(metrics_filename);
33+
ASSERT_TRUE(metrics_file.good());
34+
std::string content((std::istreambuf_iterator<char>(metrics_file)),
35+
(std::istreambuf_iterator<char>()));
36+
37+
// The output is a JSON string, which may be multi-line.
38+
// For simplicity, we'll just check for substrings.
39+
EXPECT_NE(content.find("\"flow__warnings__count\": 11"), std::string::npos);
40+
EXPECT_NE(content.find("\"flow__errors__count\": 0"), std::string::npos);
41+
EXPECT_NE(content.find("\"flow__warnings__count:UTL-20\": 10"),
42+
std::string::npos);
43+
EXPECT_NE(content.find("\"flow__warnings__count:UTL-21\": 1"),
44+
std::string::npos);
45+
EXPECT_NE(content.find("\"flow__warnings__type_count\": 2"),
46+
std::string::npos);
47+
48+
// Clean up
49+
std::remove(metrics_filename.c_str());
50+
}
51+
52+
} // namespace utl

0 commit comments

Comments
 (0)