-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Add environment var as input for SSA CFG debug log level #16581
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
base: develop
Are you sure you want to change the base?
Changes from all commits
885c2fe
ad2c681
234b252
2bdfb2c
a8facb2
06c05f1
4065c17
6869430
c10d465
e7e1338
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 |
|---|---|---|
|
|
@@ -23,6 +23,8 @@ set(sources | |
| Keccak256.h | ||
| LazyInit.h | ||
| LEB128.h | ||
| logging.cpp | ||
| logging.h | ||
| Numeric.cpp | ||
| Numeric.h | ||
| picosha2.h | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| #include <libsolutil/logging.h> | ||
|
|
||
| #include <map> | ||
| #include <optional> | ||
| #include <vector> | ||
|
|
||
| using namespace solidity; | ||
|
|
||
| struct Registry::Impl { | ||
| std::map<std::string, std::unique_ptr<Logger>, std::less<>> loggers; | ||
| // Preset levels: applied to new loggers on creation (most specific match wins) | ||
| std::vector<std::pair<std::string, LogLevel>> presets; | ||
| std::FILE* output = stderr; | ||
|
|
||
| LogLevel resolve_level(std::string const& name) const { | ||
| LogLevel result = LogLevel::info; | ||
| std::size_t best_match = 0; | ||
| bool matched = false; | ||
| for (auto const& [prefix, level] : presets) { | ||
| if (prefix.empty() || name == prefix || name.starts_with(prefix + ".")) { | ||
| if (!matched || prefix.size() >= best_match) { | ||
| best_match = prefix.size(); | ||
| result = level; | ||
| matched = true; | ||
| } | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| }; | ||
|
|
||
| Registry::Registry() : m_impl(std::make_unique<Impl>()) {} | ||
| Registry::~Registry() = default; | ||
|
|
||
| Registry& Registry::instance() { | ||
| static Registry reg; | ||
| return reg; | ||
| } | ||
|
|
||
| Logger& Registry::get(std::string const& name) { | ||
| auto it = m_impl->loggers.find(name); | ||
| if (it != m_impl->loggers.end()) | ||
| return *it->second; | ||
|
|
||
| auto level = m_impl->resolve_level(name); | ||
| auto logger = std::make_unique<Logger>(name, level, m_impl->output); | ||
| auto& ref = *logger; | ||
| m_impl->loggers.emplace(name, std::move(logger)); | ||
| return ref; | ||
| } | ||
|
|
||
| void Registry::set_level(std::string_view prefix, LogLevel level) { | ||
| // Store as preset for future loggers | ||
| std::string key(prefix); | ||
| bool found = false; | ||
| for (auto& [p, l] : m_impl->presets) { | ||
| if (p == key) { l = level; found = true; break; } | ||
| } | ||
| if (!found) | ||
| m_impl->presets.emplace_back(key, level); | ||
|
|
||
| // Apply to existing loggers | ||
| for (auto& [name, logger] : m_impl->loggers) { | ||
| if (key.empty() || name == prefix || name.starts_with(key + ".")) | ||
| logger->set_level(level); | ||
| } | ||
| } | ||
|
|
||
| void Registry::set_output(std::FILE* output) { | ||
| m_impl->output = output; | ||
| } | ||
|
|
||
| void Registry::clear() { | ||
| m_impl->loggers.clear(); | ||
| } | ||
|
|
||
| namespace solidity { | ||
|
|
||
| std::optional<LogLevel> parseLogLevel(std::string_view s) { | ||
| if (s == "trace") return LogLevel::trace; | ||
| if (s == "debug") return LogLevel::debug; | ||
| if (s == "info") return LogLevel::info; | ||
| if (s == "warn") return LogLevel::warn; | ||
| if (s == "error") return LogLevel::error; | ||
| if (s == "off") return LogLevel::off; | ||
| return std::nullopt; | ||
| } | ||
|
|
||
| } | ||
|
Collaborator
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. There's lot of stuff here that does not follow our style. Is it copied from somewhere?
Member
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. do you think it is productive to drive-by review this PR at that level especially considering in the state it is in right now? while it is being in draft and clearly not in a finalized state?
Collaborator
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. Sorry, but SSA CFG-related PRs tend to get merged very quickly, sometimes before I manage to even take a look at them so I learned that I have to act fast and leave a comment if something catches my eye. This bit wasn't my focus here, but it stood out and it wasn't very clear to me how close to completion this PR really was as I only skimmed through parts of it and it has no description (is it a normal initial version or just a messy final version?) so I decided it's better to comment on it regardless. Note that I intentionally wrapped it into a single comment rather than flood you with comments on every individual thing. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| #pragma once | ||
|
|
||
| #include <libsolutil/Exceptions.h> | ||
|
|
||
| #include <fmt/format.h> | ||
|
|
||
| #include <cstdio> | ||
| #include <memory> | ||
| #include <optional> | ||
| #include <string> | ||
| #include <string_view> | ||
|
|
||
| namespace solidity | ||
| { | ||
|
|
||
| enum class LogLevel : std::uint8_t { trace = 0, debug = 1, info = 2, warn = 3, error = 4, off = 5 }; | ||
|
|
||
| /// Guard macro: skips argument evaluation when the logger's level is too low. | ||
| /// SOL_LOG(logger, debug, "x={} y={}", expensive1(), expensive2()); | ||
| #define SOL_LOG(logger, lvl, ...) \ | ||
| do { if ((logger).should_log(::solidity::LogLevel::lvl)) [[unlikely]] (logger).lvl(__VA_ARGS__); } while (0) | ||
|
|
||
| class Logger { | ||
| public: | ||
| explicit Logger(std::string name, LogLevel level = LogLevel::info, std::FILE* output = stdout) | ||
| : m_name(std::move(name)), | ||
| m_level(static_cast<std::uint8_t>(level)), | ||
| m_output(output) {} | ||
|
|
||
| [[nodiscard]] bool should_log(LogLevel level) const noexcept { | ||
| return static_cast<std::uint8_t>(level) >= m_level; | ||
| } | ||
|
|
||
| void set_level(LogLevel level) noexcept { | ||
| m_level = static_cast<std::uint8_t>(level); | ||
| } | ||
|
|
||
| [[nodiscard]] LogLevel level() const noexcept { | ||
| return static_cast<LogLevel>(m_level); | ||
| } | ||
|
|
||
| [[nodiscard]] std::string const& name() const noexcept { return m_name; } | ||
|
|
||
| void set_output(std::FILE* output) noexcept { m_output = output; } | ||
|
|
||
| template <typename... Args> | ||
| void log(LogLevel const level, fmt::format_string<Args...> fmt, Args&&... args) const { | ||
| if (!should_log(level)) | ||
| return; | ||
| fmt::print(m_output, fmt, std::forward<Args>(args)...); | ||
| } | ||
|
|
||
| template <typename... Args> | ||
| SOL_NOINLINE void trace(fmt::format_string<Args...> fmt, Args&&... args) const { | ||
| log(LogLevel::trace, fmt, std::forward<Args>(args)...); | ||
| } | ||
|
|
||
| template <typename... Args> | ||
| SOL_NOINLINE void debug(fmt::format_string<Args...> fmt, Args&&... args) const { | ||
| log(LogLevel::debug, fmt, std::forward<Args>(args)...); | ||
| } | ||
|
|
||
| template <typename... Args> | ||
| SOL_NOINLINE void info(fmt::format_string<Args...> fmt, Args&&... args) const { | ||
| log(LogLevel::info, fmt, std::forward<Args>(args)...); | ||
| } | ||
|
|
||
| template <typename... Args> | ||
| SOL_NOINLINE void warn(fmt::format_string<Args...> fmt, Args&&... args) const { | ||
| log(LogLevel::warn, fmt, std::forward<Args>(args)...); | ||
| } | ||
|
|
||
| template <typename... Args> | ||
| SOL_NOINLINE void error(fmt::format_string<Args...> fmt, Args&&... args) const { | ||
| log(LogLevel::error, fmt, std::forward<Args>(args)...); | ||
| } | ||
|
|
||
| private: | ||
| std::string m_name; | ||
| std::uint8_t m_level; | ||
| std::FILE* m_output; | ||
| }; | ||
|
|
||
| class Registry { | ||
| public: | ||
| static Registry& instance(); | ||
|
|
||
| Logger& get(std::string const& name); | ||
| void set_level(std::string_view prefix, LogLevel level); | ||
| void set_output(std::FILE* output); | ||
| void clear(); | ||
|
|
||
| private: | ||
| Registry(); | ||
| ~Registry(); | ||
| struct Impl; | ||
| std::unique_ptr<Impl> m_impl; | ||
| }; | ||
|
|
||
| std::optional<LogLevel> parseLogLevel(std::string_view s); | ||
|
|
||
| } |
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.
Coding style error