diff --git a/barretenberg/cpp/src/barretenberg/bb/cli.cpp b/barretenberg/cpp/src/barretenberg/bb/cli.cpp index c9d7a6f1d070..78aee2772cfa 100644 --- a/barretenberg/cpp/src/barretenberg/bb/cli.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/cli.cpp @@ -749,8 +749,11 @@ int parse_and_run_cli_command(int argc, char* argv[]) // If writing to an output folder, make sure it exists. std::filesystem::create_directories(output_path); } - debug_logging = flags.debug; - verbose_logging = debug_logging || flags.verbose; + if (flags.debug) { + bb_log_level = LogLevel::DEBUG; + } else if (flags.verbose) { + bb_log_level = LogLevel::VERBOSE; + } slow_low_memory = flags.slow_low_memory; #if !defined(__wasm__) || defined(ENABLE_WASM_BENCH) if (!flags.storage_budget.empty()) { diff --git a/barretenberg/cpp/src/barretenberg/common/log.cpp b/barretenberg/cpp/src/barretenberg/common/log.cpp index 65b3354e0ec4..74c9d3305dbc 100644 --- a/barretenberg/cpp/src/barretenberg/common/log.cpp +++ b/barretenberg/cpp/src/barretenberg/common/log.cpp @@ -5,16 +5,18 @@ #include "barretenberg/common/log.hpp" #ifndef __wasm__ -bool verbose_logging = std::getenv("BB_VERBOSE") == nullptr ? false : std::string(std::getenv("BB_VERBOSE")) == "1"; +// Default log level is INFO. +LogLevel bb_log_level = []() { + const char* verbose_ptr = std::getenv("BB_VERBOSE"); + std::string verbose_str = verbose_ptr == nullptr ? "0" : std::string(verbose_ptr); + return verbose_str == "1" ? LogLevel::VERBOSE : LogLevel::INFO; +}(); #else -bool verbose_logging = true; +LogLevel bb_log_level = LogLevel::VERBOSE; #endif -// Used for `debug` in log.hpp. -bool debug_logging = false; - // Used for `log_function` in log.hpp. Defaults to `logstr`. -LogFunction log_function = [](LogLevel /*unused*/, const char* msg) { logstr(msg); }; +LogFunction log_function = [](LogLevel /*unused*/, const std::string& msg) { logstr(msg.c_str()); }; void set_log_function(LogFunction new_log_function) { diff --git a/barretenberg/cpp/src/barretenberg/common/log.hpp b/barretenberg/cpp/src/barretenberg/common/log.hpp index 8d70c2906f34..45ed9b66107e 100644 --- a/barretenberg/cpp/src/barretenberg/common/log.hpp +++ b/barretenberg/cpp/src/barretenberg/common/log.hpp @@ -7,7 +7,6 @@ #include #include "barretenberg/env/logstr.hpp" -#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp" #define BENCHMARK_INFO_PREFIX "##BENCHMARK_INFO_PREFIX##" #define BENCHMARK_INFO_SEPARATOR "#" @@ -58,54 +57,52 @@ template std::string benchmark_format(Args... args) return os.str(); } +// Log levels from TS foundation/src/log/log-levels.ts: +// ['silent', 'fatal', 'error', 'warn', 'info', 'verbose', 'debug', 'trace'] +// Map: 0=silent, 1=fatal, 2=error, 3=warn, 4=info, 5=verbose, 6=debug, 7=trace enum class LogLevel : int { - DEBUG = 0, - INFO = 1, - VERBOSE = 2, - IMPORTANT = 3, + SILENT = 0, // Works ok as 0 assuming nothing logs as SILENT. + FATAL = 1, + ERROR = 2, + WARN = 3, + INFO = 4, + VERBOSE = 5, + DEBUG = 6, + TRACE = 7, }; +extern LogLevel bb_log_level; // This allows the logging sink to be customized. Useful for Typescript use-cases. -using LogFunction = std::function; +using LogFunction = std::function; extern LogFunction log_function; void set_log_function(LogFunction new_log_function); -extern bool debug_logging; -// In release mode (e.g., NDEBUG is defined), we don't compile debug logs. +// This logs (using log_function) if the log level is enabled. +// NOTE: Evaluation of __VA_ARGS__ is lazy since it's inside the if statement. +#define log_(level, ...) \ + do { \ + if (level <= bb_log_level) { \ + log_function(level, format(__VA_ARGS__)); \ + } \ + } while (0) + +#define log_fatal(...) log_(LogLevel::FATAL, __VA_ARGS__) +#define log_error(...) log_(LogLevel::ERROR, __VA_ARGS__) +#define log_warn(...) log_(LogLevel::WARN, __VA_ARGS__) +#define important(...) log_(LogLevel::WARN, "important: ", __VA_ARGS__) +#define info(...) log_(LogLevel::INFO, __VA_ARGS__) +#define vinfo(...) log_(LogLevel::VERBOSE, __VA_ARGS__) +#define log_verbose(...) log_(LogLevel::VERBOSE, __VA_ARGS__) + +// The following logging levels are only compiled in debug mode (i.e., NDEBUG is not defined). #ifndef NDEBUG -#define debug(...) debug_([&]() { return format(__VA_ARGS__); }) +#define debug(...) log_(LogLevel::DEBUG, __VA_ARGS__) +#define log_trace(...) log_(LogLevel::TRACE, __VA_ARGS__) #else #define debug(...) (void)0 +#define log_trace(...) (void)0 #endif -// We take a function so that evaluation is lazy. -inline void debug_(std::function func) -{ - if (debug_logging) { - log_function(LogLevel::DEBUG, func().c_str()); - } -} - -template inline void info(Args... args) -{ - log_function(LogLevel::INFO, format(args...).c_str()); -} - -#define vinfo(...) vinfo_([&]() { return format(__VA_ARGS__); }) - -extern bool verbose_logging; -inline void vinfo_(std::function func) -{ - if (verbose_logging) { - log_function(LogLevel::VERBOSE, func().c_str()); - } -} - -template inline void important(Args... args) -{ - log_function(LogLevel::IMPORTANT, format("important: ", args...).c_str()); -} - /** * @brief Info used to store circuit statistics during CI/CD with concrete structure. Writes straight to log * diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index ffbef109a8ce..c6109b06a86f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -278,9 +278,9 @@ T deserialize_msgpack_compact(std::vector&& buf, std::function(buf.data())[1]; diff --git a/barretenberg/cpp/src/barretenberg/nodejs_module/avm_simulate/avm_simulate_napi.cpp b/barretenberg/cpp/src/barretenberg/nodejs_module/avm_simulate/avm_simulate_napi.cpp index 6195303a7da4..283f9488556e 100644 --- a/barretenberg/cpp/src/barretenberg/nodejs_module/avm_simulate/avm_simulate_napi.cpp +++ b/barretenberg/cpp/src/barretenberg/nodejs_module/avm_simulate/avm_simulate_napi.cpp @@ -18,32 +18,43 @@ namespace { // Log levels from TS foundation/src/log/log-levels.ts: ['silent', 'fatal', 'error', 'warn', 'info', 'verbose', 'debug', // 'trace'] Map: 0=silent, 1=fatal, 2=error, 3=warn, 4=info, 5=verbose, 6=debug, 7=trace -constexpr int LOG_LEVEL_VERBOSE = 5; -constexpr int LOG_LEVEL_TRACE = 7; -// Helper to set logging flags based on TS log level -inline void set_logging_from_level(int log_level) +// Helper to set logging level based on TS log level +inline void set_logging_from_level(int ts_log_level) { - // Turn verbose_logging on if log level is verbose (5) or above - verbose_logging = (log_level >= LOG_LEVEL_VERBOSE); - // Turn debug_logging on if log level is trace (7) or above - debug_logging = (log_level >= LOG_LEVEL_TRACE); + // Map TS log level (0-7) to C++ LogLevel enum + // TS: 0=silent, 1=fatal, 2=error, 3=warn, 4=info, 5=verbose, 6=debug, 7=trace + // C++: SILENT=0, FATAL=1, ERROR=2, WARN=3, INFO=4, VERBOSE=5, DEBUG=6, TRACE=7 + // They map 1:1 + if (ts_log_level >= 0 && ts_log_level <= 7) { + bb_log_level = static_cast(ts_log_level); + } else { + log_warn("Invalid log level from TypeScript: ", ts_log_level, ". Using default."); + } } // Map C++ LogLevel enum to TypeScript log level string -// C++ LogLevel: DEBUG=0, INFO=1, VERBOSE=2, IMPORTANT=3 +// C++ LogLevel: SILENT=0, FATAL=1, ERROR=2, WARN=3, INFO=4, VERBOSE=5, DEBUG=6, TRACE=7 // TS LogLevels: ['silent', 'fatal', 'error', 'warn', 'info', 'verbose', 'debug', 'trace'] inline const char* cpp_log_level_to_ts(LogLevel level) { switch (level) { - case LogLevel::DEBUG: - return "debug"; + case LogLevel::SILENT: + return "silent"; + case LogLevel::FATAL: + return "fatal"; + case LogLevel::ERROR: + return "error"; + case LogLevel::WARN: + return "warn"; case LogLevel::INFO: return "info"; case LogLevel::VERBOSE: return "verbose"; - case LogLevel::IMPORTANT: - return "warn"; + case LogLevel::DEBUG: + return "debug"; + case LogLevel::TRACE: + return "trace"; default: return "info"; } @@ -53,18 +64,18 @@ inline const char* cpp_log_level_to_ts(LogLevel level) // This allows C++ logging to call back to TypeScript logger from worker threads LogFunction create_log_function_from_tsfn(const std::shared_ptr& logger_tsfn) { - return [logger_tsfn](LogLevel level, const char* msg) { + return [logger_tsfn](LogLevel level, const std::string& msg) { // Convert C++ LogLevel to TS log level string const char* ts_level = cpp_log_level_to_ts(level); - std::string msg_str(msg); // Call TypeScript logger function on the JS main thread // Using BlockingCall to ensure synchronous execution // Ignore errors - logging failures shouldn't crash the simulation - logger_tsfn->BlockingCall([ts_level, msg_str](Napi::Env env, Napi::Function js_logger) { + // NOTE: We copy the string because it might be destroyed before the callback is called. + logger_tsfn->BlockingCall([ts_level, msg](Napi::Env env, Napi::Function js_logger) { // Create arguments: (level: string, msg: string) auto level_js = Napi::String::New(env, ts_level); - auto msg_js = Napi::String::New(env, msg_str); + auto msg_js = Napi::String::New(env, msg); js_logger.Call({ level_js, msg_js }); }); };