From 7b58655bd0beb1fb873c3bf3cfa001b09d564322 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Mon, 5 Jan 2026 23:59:47 +0000 Subject: [PATCH 01/22] add buffer logging, allows printing before thrown errors --- projects/miopen/src/include/miopen/errors.hpp | 11 ++++++++ projects/miopen/src/include/miopen/logger.hpp | 25 +++++++++++-------- projects/miopen/src/logger.cpp | 6 +++++ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/projects/miopen/src/include/miopen/errors.hpp b/projects/miopen/src/include/miopen/errors.hpp index d98004230945..94b4bee362d0 100644 --- a/projects/miopen/src/include/miopen/errors.hpp +++ b/projects/miopen/src/include/miopen/errors.hpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -63,6 +64,16 @@ MIOPEN_EXPORT std::string HIPErrorMessage(int error, const std::string& msg = "" template [[noreturn]] void MIOpenThrow(const std::string& file, int line, Params&&... args) { + size_t i = miopen::log_buffer_i; + std::cerr << "Buffered " << miopen::log_buffer_i << " messages." << std::endl; + do + { + if(miopen::log_buffer[i] != "") + { + std::cerr << miopen::log_buffer[i]; + } + i = (i + 1) % miopen::log_buffer_size; + } while(i != miopen::log_buffer_i); throw miopen::Exception(std::forward(args)...).SetContext(file, line); } diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index 6d9e1932febf..c398665ab0da 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -139,6 +139,9 @@ namespace miopen { +extern size_t log_buffer_size, log_buffer_i; +extern std::vector log_buffer; + template std::ostream& LogRange(std::ostream& os, Range&& r, std::string delim) { @@ -364,16 +367,18 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, #define MIOPEN_GET_FN_NAME miopen::LoggingParseFunction(__func__, __PRETTY_FUNCTION__) #endif -#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ - do \ - { \ - if(miopen::IsLogging(level, disableQuieting)) \ - { \ - std::ostringstream miopen_log_ss; \ - miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ - << __VA_ARGS__ << std::endl; \ - std::cerr << miopen_log_ss.str(); \ - } \ +#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ + do \ + { \ + std::ostringstream miopen_log_ss; \ + miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ + << __VA_ARGS__ << std::endl; \ + miopen::log_buffer[miopen::log_buffer_i % miopen::log_buffer_size] = miopen_log_ss.str(); \ + miopen::log_buffer_i++; \ + if(miopen::IsLogging(level, disableQuieting)) \ + { \ + std::cerr << miopen_log_ss.str(); \ + } \ } while(false) #define MIOPEN_LOG_XQ_(level, disableQuieting, fn_name, ...) \ diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index d7b5ba5be159..b2342f4e498a 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -68,8 +68,14 @@ MIOPEN_DECLARE_ENV_VAR_BOOL(MIOPEN_ENABLE_LOGGING_ROCTX) /// Disable logging quieting. MIOPEN_DECLARE_ENV_VAR_BOOL(MIOPEN_DEBUG_LOGGING_QUIETING_DISABLE) +MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_BUFFER_SIZE, 128); + namespace miopen { +size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); +size_t log_buffer_i = 0; +std::vector log_buffer(log_buffer_size, ""); + namespace debug { // NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) From 714367a73fed5285d87423bb62419d2731a55e5c Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Tue, 6 Jan 2026 21:52:03 +0000 Subject: [PATCH 02/22] limit buffered logs to I2, output on error log, add OutputBufferedLog function --- projects/miopen/src/include/miopen/errors.hpp | 11 +----- projects/miopen/src/include/miopen/logger.hpp | 34 ++++++++++++------- projects/miopen/src/logger.cpp | 20 +++++++++++ 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/projects/miopen/src/include/miopen/errors.hpp b/projects/miopen/src/include/miopen/errors.hpp index 94b4bee362d0..9335abeee1af 100644 --- a/projects/miopen/src/include/miopen/errors.hpp +++ b/projects/miopen/src/include/miopen/errors.hpp @@ -64,16 +64,7 @@ MIOPEN_EXPORT std::string HIPErrorMessage(int error, const std::string& msg = "" template [[noreturn]] void MIOpenThrow(const std::string& file, int line, Params&&... args) { - size_t i = miopen::log_buffer_i; - std::cerr << "Buffered " << miopen::log_buffer_i << " messages." << std::endl; - do - { - if(miopen::log_buffer[i] != "") - { - std::cerr << miopen::log_buffer[i]; - } - i = (i + 1) % miopen::log_buffer_size; - } while(i != miopen::log_buffer_i); + miopen::OutputBufferedLogs(); throw miopen::Exception(std::forward(args)...).SetContext(file, line); } diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index c398665ab0da..f133ebad420e 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -142,6 +142,8 @@ namespace miopen { extern size_t log_buffer_size, log_buffer_i; extern std::vector log_buffer; +void OutputBufferedLogs(); + template std::ostream& LogRange(std::ostream& os, Range&& r, std::string delim) { @@ -367,18 +369,26 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, #define MIOPEN_GET_FN_NAME miopen::LoggingParseFunction(__func__, __PRETTY_FUNCTION__) #endif -#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ - do \ - { \ - std::ostringstream miopen_log_ss; \ - miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ - << __VA_ARGS__ << std::endl; \ - miopen::log_buffer[miopen::log_buffer_i % miopen::log_buffer_size] = miopen_log_ss.str(); \ - miopen::log_buffer_i++; \ - if(miopen::IsLogging(level, disableQuieting)) \ - { \ - std::cerr << miopen_log_ss.str(); \ - } \ +#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ + do \ + { \ + std::ostringstream miopen_log_ss; \ + miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ + << __VA_ARGS__ << std::endl; \ + if(level < miopen::LoggingLevel::Trace) \ + { \ + miopen::log_buffer[miopen::log_buffer_i % miopen::log_buffer_size] = \ + miopen_log_ss.str(); \ + miopen::log_buffer_i++; \ + } \ + if(miopen::IsLogging(level, disableQuieting)) \ + { \ + std::cerr << miopen_log_ss.str(); \ + } \ + if(level == miopen::LoggingLevel::Error) \ + { \ + miopen::OutputBufferedLogs(); \ + } \ } while(false) #define MIOPEN_LOG_XQ_(level, disableQuieting, fn_name, ...) \ diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index b2342f4e498a..838c20ff4492 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -24,12 +24,14 @@ * *******************************************************************************/ #include +#include #include #include #include #include #include +#include #include #include #include @@ -76,6 +78,24 @@ size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); size_t log_buffer_i = 0; std::vector log_buffer(log_buffer_size, ""); +void OutputBufferedLogs() +{ + auto filename = + fs::temp_directory_path() / ("miopen_error_" + std::to_string(getpid()) + ".log"); + std::cerr << "Buffered " << miopen::log_buffer_i << " messages to file: " << filename.string() + << std::endl; + auto err_file = std::ofstream{filename}; + size_t i = miopen::log_buffer_i; + do + { + if(miopen::log_buffer[i] != "") + { + err_file << miopen::log_buffer[i]; + } + i = (i + 1) % miopen::log_buffer_size; + } while(i != miopen::log_buffer_i); +} + namespace debug { // NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) From 593859ad08e37d5e1456467bec3ef58260afd16b Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Tue, 6 Jan 2026 22:19:47 +0000 Subject: [PATCH 03/22] add throws to the error log --- projects/miopen/src/include/miopen/errors.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/miopen/src/include/miopen/errors.hpp b/projects/miopen/src/include/miopen/errors.hpp index 9335abeee1af..b1b41e735262 100644 --- a/projects/miopen/src/include/miopen/errors.hpp +++ b/projects/miopen/src/include/miopen/errors.hpp @@ -64,8 +64,9 @@ MIOPEN_EXPORT std::string HIPErrorMessage(int error, const std::string& msg = "" template [[noreturn]] void MIOpenThrow(const std::string& file, int line, Params&&... args) { - miopen::OutputBufferedLogs(); - throw miopen::Exception(std::forward(args)...).SetContext(file, line); + auto exe = miopen::Exception(std::forward(args)...); + MIOPEN_LOG_E_FROM(file + ":" + std::to_string(line), exe.message); + throw exe.SetContext(file, line); } #define MIOPEN_THROW(...) \ From 41fc8f68eb584feb6b2c3233d5cb1ce272f226b9 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 14 Jan 2026 19:30:00 +0000 Subject: [PATCH 04/22] set log buffer to thread_local variable, add unit test --- projects/miopen/src/include/miopen/logger.hpp | 7 +- projects/miopen/src/logger.cpp | 6 +- projects/miopen/test/gtest/log.cpp | 79 +++++++++++++++++++ projects/miopen/test/gtest/log.hpp | 2 + projects/miopen/test/gtest/log_test.cpp | 2 + 5 files changed, 90 insertions(+), 6 deletions(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index f133ebad420e..8213d7036ada 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -139,8 +139,8 @@ namespace miopen { -extern size_t log_buffer_size, log_buffer_i; -extern std::vector log_buffer; +extern thread_local size_t log_buffer_size, log_buffer_i; +extern thread_local std::vector log_buffer; void OutputBufferedLogs(); @@ -385,7 +385,8 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, { \ std::cerr << miopen_log_ss.str(); \ } \ - if(level == miopen::LoggingLevel::Error) \ + if(level == miopen::LoggingLevel::Error && \ + !miopen::IsLogging(miopen::LoggingLevel::Info2, disableQuieting)) \ { \ miopen::OutputBufferedLogs(); \ } \ diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 838c20ff4492..3d634a8e705a 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -74,9 +74,9 @@ MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_BUFFER_SIZE, 128); namespace miopen { -size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); -size_t log_buffer_i = 0; -std::vector log_buffer(log_buffer_size, ""); +thread_local size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); +thread_local size_t log_buffer_i = 0; +thread_local std::vector log_buffer(log_buffer_size, ""); void OutputBufferedLogs() { diff --git a/projects/miopen/test/gtest/log.cpp b/projects/miopen/test/gtest/log.cpp index 7f95f794674d..eb138014f066 100644 --- a/projects/miopen/test/gtest/log.cpp +++ b/projects/miopen/test/gtest/log.cpp @@ -29,7 +29,9 @@ #include "../lib_env_var.hpp" #include +#include #include +#include #include "../random.hpp" #if MIOPEN_BACKEND_OPENCL @@ -44,6 +46,8 @@ #define MDEXE "./bin/MIOpenDriver" #endif +MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_LEVEL) + const std::string logConv = "MIOpen(" BKEND "): Command [LogCmdConvolution] " MDEXE " conv -n 128 -c 3 -H 32 -W 32 -k " "64 -y 3 -x 3 -p 1 -q 1 -u 1 -v 1 -l 1 -j 1 -m conv -g 1 -F 1 -t 1"; @@ -330,3 +334,78 @@ void TestLogCmdBNormFusion(std::function(miopen::log_buffer_size, ""); + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + MIOPEN_LOG_E("error"); + ASSERT_TRUE(fs::exists(filename)); + std::cerr << filename << std::endl; + auto log_file = std::ifstream{filename}; + while(std::getline(log_file, line)) + { + std::cerr << line << std::endl; + switch(line_i) + { + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: + ASSERT_FALSE(isSubStr(line, "trace")); + ASSERT_TRUE(isSubStr(line, "error")); + break; + } + line_i++; + } + fs::remove(filename); + + // test log dump after throw + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + EXPECT_ANY_THROW(MIOPEN_THROW("throw")); + + EXPECT_TRUE(fs::exists(filename)); + log_file = std::ifstream{filename}; + line_i = 0; + while(std::getline(log_file, line)) + { + switch(line_i) + { + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: ASSERT_TRUE(isSubStr(line, "throw")); break; + } + line_i++; + } + fs::remove(filename); + + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + miopen::env::update(MIOPEN_LOG_LEVEL, 6); // miopen::LoggingLevel::Info2); + // log messages + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + // test log dump after error + MIOPEN_LOG_E("error"); + ASSERT_FALSE(fs::exists(filename)); +} diff --git a/projects/miopen/test/gtest/log.hpp b/projects/miopen/test/gtest/log.hpp index 6c055c96bc6b..44a27ba5a596 100644 --- a/projects/miopen/test/gtest/log.hpp +++ b/projects/miopen/test/gtest/log.hpp @@ -82,3 +82,5 @@ void TestLogCmdCBAFusion(std::function void TestLogCmdBNormFusion(std::function const& func, std::string sub_str, bool set_env); + +void TestLogBuffer(); diff --git a/projects/miopen/test/gtest/log_test.cpp b/projects/miopen/test/gtest/log_test.cpp index 2752023f8a86..868ede9e59cc 100644 --- a/projects/miopen/test/gtest/log_test.cpp +++ b/projects/miopen/test/gtest/log_test.cpp @@ -48,4 +48,6 @@ TEST(CPU_LOG_TEST_FUSION_NONE, AssertTestLogCmdBNormFusionOutput) TestLogCmdBNormFusion(miopen::debug::LogCmdFusion, logBnormActiv, true); } +TEST(CPU_LOG_TEST_ASSERT_NONE, AssertLogBuffer) { TestLogBuffer(); } + #endif From 18380ad2d14f31698b6b33e048fddf0610b3729c Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 14 Jan 2026 19:43:19 +0000 Subject: [PATCH 05/22] cleanup logging definition --- projects/miopen/src/include/miopen/logger.hpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index 8213d7036ada..24449a56e06a 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -375,20 +375,22 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, std::ostringstream miopen_log_ss; \ miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ << __VA_ARGS__ << std::endl; \ - if(level < miopen::LoggingLevel::Trace) \ - { \ - miopen::log_buffer[miopen::log_buffer_i % miopen::log_buffer_size] = \ - miopen_log_ss.str(); \ - miopen::log_buffer_i++; \ - } \ if(miopen::IsLogging(level, disableQuieting)) \ { \ std::cerr << miopen_log_ss.str(); \ } \ - if(level == miopen::LoggingLevel::Error && \ - !miopen::IsLogging(miopen::LoggingLevel::Info2, disableQuieting)) \ + if(!miopen::IsLogging(miopen::LoggingLevel::Info2, disableQuieting)) \ { \ - miopen::OutputBufferedLogs(); \ + if(level < miopen::LoggingLevel::Trace) \ + { \ + miopen::log_buffer[miopen::log_buffer_i % miopen::log_buffer_size] = \ + miopen_log_ss.str(); \ + miopen::log_buffer_i++; \ + } \ + if(level == miopen::LoggingLevel::Error) \ + { \ + miopen::OutputBufferedLogs(); \ + } \ } \ } while(false) From f60e7d668a397fd3efdf700d21205c0bb26de4c9 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 14 Jan 2026 19:56:07 +0000 Subject: [PATCH 06/22] add doc description of log env var --- projects/miopen/docs/how-to/debug-log.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/projects/miopen/docs/how-to/debug-log.rst b/projects/miopen/docs/how-to/debug-log.rst index 3c891c35313e..1f908e560389 100644 --- a/projects/miopen/docs/how-to/debug-log.rst +++ b/projects/miopen/docs/how-to/debug-log.rst @@ -48,6 +48,12 @@ environmental variables to control logging. Both variables are disabled by defau * ``MIOPEN_WARN_SEARCH``: Elevate log messages for Search to warnings. +* ``MIOPEN_LOG_BUFFER_SIZE``: Message length of the Info2 buffer. + If MIOPEN_LOG_LEVEL is less than 6, then log messages will be buffered. + The buffered logs will be dumped to a log file when MIOpen logs an error message, + or an error is thrown by MIOpen. + This log can be found in /tmp/miopen_error_. + .. note:: If you require technical support, include the console log that is produced from these settings: From edad33083768ac3a7f49d933e081af6464fe59d9 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 14 Jan 2026 22:03:46 +0000 Subject: [PATCH 07/22] update log buffer gtest --- projects/miopen/test/gtest/log.cpp | 128 ++++++++++++------------ projects/miopen/test/gtest/log_test.cpp | 4 +- 2 files changed, 68 insertions(+), 64 deletions(-) diff --git a/projects/miopen/test/gtest/log.cpp b/projects/miopen/test/gtest/log.cpp index eb138014f066..0695786af1a2 100644 --- a/projects/miopen/test/gtest/log.cpp +++ b/projects/miopen/test/gtest/log.cpp @@ -28,8 +28,8 @@ #include "get_handle.hpp" #include "../lib_env_var.hpp" +#include #include -#include #include #include #include "../random.hpp" @@ -46,8 +46,6 @@ #define MDEXE "./bin/MIOpenDriver" #endif -MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_LEVEL) - const std::string logConv = "MIOpen(" BKEND "): Command [LogCmdConvolution] " MDEXE " conv -n 128 -c 3 -H 32 -W 32 -k " "64 -y 3 -x 3 -p 1 -q 1 -u 1 -v 1 -l 1 -j 1 -m conv -g 1 -F 1 -t 1"; @@ -343,69 +341,75 @@ void TestLogBuffer() size_t line_i = 0; std::string line; - miopen::env::update(MIOPEN_LOG_LEVEL, 5); // miopen::LoggingLevel::Info); - // test log dump after error - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); - MIOPEN_LOG_W("warn"); - MIOPEN_LOG_I("info"); - MIOPEN_LOG_I2("info2"); - MIOPEN_LOG_T("trace"); - MIOPEN_LOG_E("error"); - ASSERT_TRUE(fs::exists(filename)); - std::cerr << filename << std::endl; - auto log_file = std::ifstream{filename}; - while(std::getline(log_file, line)) { - std::cerr << line << std::endl; - switch(line_i) + ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, + "5"); // miopen::LoggingLevel::Info + // test log dump after error + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + MIOPEN_LOG_E("error"); + ASSERT_TRUE(fs::exists(filename)); + std::cerr << filename << std::endl; + auto log_file = std::ifstream{filename}; + while(std::getline(log_file, line)) { - case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; - case 1: ASSERT_TRUE(isSubStr(line, "info")); break; - case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; - case 3: - ASSERT_FALSE(isSubStr(line, "trace")); - ASSERT_TRUE(isSubStr(line, "error")); - break; + std::cerr << line << std::endl; + switch(line_i) + { + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: + ASSERT_FALSE(isSubStr(line, "trace")); + ASSERT_TRUE(isSubStr(line, "error")); + break; + } + line_i++; } - line_i++; - } - fs::remove(filename); - - // test log dump after throw - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); - MIOPEN_LOG_W("warn"); - MIOPEN_LOG_I("info"); - MIOPEN_LOG_I2("info2"); - MIOPEN_LOG_T("trace"); - EXPECT_ANY_THROW(MIOPEN_THROW("throw")); - - EXPECT_TRUE(fs::exists(filename)); - log_file = std::ifstream{filename}; - line_i = 0; - while(std::getline(log_file, line)) - { - switch(line_i) + fs::remove(filename); + + // test log dump after throw + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + EXPECT_ANY_THROW(MIOPEN_THROW("throw")); + + EXPECT_TRUE(fs::exists(filename)); + log_file = std::ifstream{filename}; + line_i = 0; + while(std::getline(log_file, line)) { - case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; - case 1: ASSERT_TRUE(isSubStr(line, "info")); break; - case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; - case 3: ASSERT_TRUE(isSubStr(line, "throw")); break; + switch(line_i) + { + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: ASSERT_TRUE(isSubStr(line, "throw")); break; + } + line_i++; } - line_i++; + fs::remove(filename); + } + + { + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, + "6"); // miopen::LoggingLevel::Info2 + // log messages + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + // test log dump after error + MIOPEN_LOG_E("error"); + ASSERT_FALSE(fs::exists(filename)); } - fs::remove(filename); - - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); - miopen::env::update(MIOPEN_LOG_LEVEL, 6); // miopen::LoggingLevel::Info2); - // log messages - MIOPEN_LOG_W("warn"); - MIOPEN_LOG_I("info"); - MIOPEN_LOG_I2("info2"); - MIOPEN_LOG_T("trace"); - // test log dump after error - MIOPEN_LOG_E("error"); - ASSERT_FALSE(fs::exists(filename)); } diff --git a/projects/miopen/test/gtest/log_test.cpp b/projects/miopen/test/gtest/log_test.cpp index 868ede9e59cc..c8c1537a96ef 100644 --- a/projects/miopen/test/gtest/log_test.cpp +++ b/projects/miopen/test/gtest/log_test.cpp @@ -38,6 +38,8 @@ TEST(CPU_LOG_TEST_ASSERT_NONE, AssertLogFindCmdOutput) TestLogFun(miopen::debug::LogCmdFindConvolution, logFindConv, true); } +TEST(CPU_LOG_TEST_ASSERT_NONE, AssertLogBuffer) { TestLogBuffer(); } + TEST(CPU_LOG_TEST_FUSION_NONE, AssertTestLogCmdCBAFusionOutput) { TestLogCmdCBAFusion(miopen::debug::LogCmdFusion, logFusionConvBiasActiv, true); @@ -48,6 +50,4 @@ TEST(CPU_LOG_TEST_FUSION_NONE, AssertTestLogCmdBNormFusionOutput) TestLogCmdBNormFusion(miopen::debug::LogCmdFusion, logBnormActiv, true); } -TEST(CPU_LOG_TEST_ASSERT_NONE, AssertLogBuffer) { TestLogBuffer(); } - #endif From a88cf62d1d929c069a542175160d2721eb295527 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 14 Jan 2026 23:28:12 +0000 Subject: [PATCH 08/22] add to change log, split gtest for log buffer --- projects/miopen/CHANGELOG.md | 1 + projects/miopen/test/gtest/log.cpp | 133 ++++++++++++------------ projects/miopen/test/gtest/log.hpp | 4 +- projects/miopen/test/gtest/log_test.cpp | 4 +- 4 files changed, 74 insertions(+), 68 deletions(-) diff --git a/projects/miopen/CHANGELOG.md b/projects/miopen/CHANGELOG.md index 538f1013e78d..2dd7953f1ec5 100644 --- a/projects/miopen/CHANGELOG.md +++ b/projects/miopen/CHANGELOG.md @@ -6,6 +6,7 @@ Full documentation for MIOpen is available [here](https://rocm.docs.amd.com/proj ### Added * New API entry-points `miopenBatchNormalizationForwardInferenceInvVariance` and `miopenBatchNormForwardInferenceActivationInvVariance` to support hipDNN. +* Log level Info2 dumped to file (/tmp/miopen_error_) on error log or MIOpen throw. ### Optimized * Added `MIOPEN_SEARCH_CUTOFF` option which can reduce tuning times by skipping slow solvers and kernels diff --git a/projects/miopen/test/gtest/log.cpp b/projects/miopen/test/gtest/log.cpp index 0695786af1a2..a4d390931c9c 100644 --- a/projects/miopen/test/gtest/log.cpp +++ b/projects/miopen/test/gtest/log.cpp @@ -333,83 +333,84 @@ void TestLogCmdBNormFusion(std::function log_level_env(MIOPEN_LOG_LEVEL, + "5"); // miopen::LoggingLevel::Info + // test log dump after error + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + MIOPEN_LOG_E("error"); + ASSERT_TRUE(fs::exists(filename)); + auto log_file = std::ifstream{filename}; + while(std::getline(log_file, line)) { - ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, - "5"); // miopen::LoggingLevel::Info - // test log dump after error - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); - MIOPEN_LOG_W("warn"); - MIOPEN_LOG_I("info"); - MIOPEN_LOG_I2("info2"); - MIOPEN_LOG_T("trace"); - MIOPEN_LOG_E("error"); - ASSERT_TRUE(fs::exists(filename)); - std::cerr << filename << std::endl; - auto log_file = std::ifstream{filename}; - while(std::getline(log_file, line)) + switch(line_i) { - std::cerr << line << std::endl; - switch(line_i) - { - case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; - case 1: ASSERT_TRUE(isSubStr(line, "info")); break; - case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; - case 3: - ASSERT_FALSE(isSubStr(line, "trace")); - ASSERT_TRUE(isSubStr(line, "error")); - break; - } - line_i++; + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: + ASSERT_FALSE(isSubStr(line, "trace")); + ASSERT_TRUE(isSubStr(line, "error")); + break; } - fs::remove(filename); - - // test log dump after throw - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); - MIOPEN_LOG_W("warn"); - MIOPEN_LOG_I("info"); - MIOPEN_LOG_I2("info2"); - MIOPEN_LOG_T("trace"); - EXPECT_ANY_THROW(MIOPEN_THROW("throw")); - - EXPECT_TRUE(fs::exists(filename)); - log_file = std::ifstream{filename}; - line_i = 0; - while(std::getline(log_file, line)) + line_i++; + } + fs::remove(filename); + + // test log dump after throw + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + EXPECT_ANY_THROW(MIOPEN_THROW("throw")); + + EXPECT_TRUE(fs::exists(filename)); + log_file = std::ifstream{filename}; + line_i = 0; + while(std::getline(log_file, line)) + { + switch(line_i) { - switch(line_i) - { - case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; - case 1: ASSERT_TRUE(isSubStr(line, "info")); break; - case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; - case 3: ASSERT_TRUE(isSubStr(line, "throw")); break; - } - line_i++; + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: ASSERT_TRUE(isSubStr(line, "throw")); break; } - fs::remove(filename); + line_i++; } + fs::remove(filename); +} - { - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); - ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, - "6"); // miopen::LoggingLevel::Info2 - // log messages - MIOPEN_LOG_W("warn"); - MIOPEN_LOG_I("info"); - MIOPEN_LOG_I2("info2"); - MIOPEN_LOG_T("trace"); - // test log dump after error - MIOPEN_LOG_E("error"); - ASSERT_FALSE(fs::exists(filename)); - } +void TestLogBufferOff() +{ + auto filename = + fs::temp_directory_path() / ("miopen_error_" + std::to_string(getpid()) + ".log"); + std::string line; + + ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, + "6"); // miopen::LoggingLevel::Info2 + + miopen::log_buffer_i = 0; + miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + // log messages + MIOPEN_LOG_W("warn"); + MIOPEN_LOG_I("info"); + MIOPEN_LOG_I2("info2"); + MIOPEN_LOG_T("trace"); + // test log dump after error + MIOPEN_LOG_E("error"); + ASSERT_FALSE(fs::exists(filename)); } diff --git a/projects/miopen/test/gtest/log.hpp b/projects/miopen/test/gtest/log.hpp index 44a27ba5a596..b89af35208d2 100644 --- a/projects/miopen/test/gtest/log.hpp +++ b/projects/miopen/test/gtest/log.hpp @@ -83,4 +83,6 @@ void TestLogCmdBNormFusion(std::function Date: Thu, 15 Jan 2026 08:55:38 -0600 Subject: [PATCH 09/22] Update projects/miopen/docs/how-to/debug-log.rst Co-authored-by: Matt Williams --- projects/miopen/docs/how-to/debug-log.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/miopen/docs/how-to/debug-log.rst b/projects/miopen/docs/how-to/debug-log.rst index 1f908e560389..8c69a23bdbe5 100644 --- a/projects/miopen/docs/how-to/debug-log.rst +++ b/projects/miopen/docs/how-to/debug-log.rst @@ -49,7 +49,7 @@ environmental variables to control logging. Both variables are disabled by defau * ``MIOPEN_WARN_SEARCH``: Elevate log messages for Search to warnings. * ``MIOPEN_LOG_BUFFER_SIZE``: Message length of the Info2 buffer. - If MIOPEN_LOG_LEVEL is less than 6, then log messages will be buffered. + If ``MIOPEN_LOG_LEVEL`` is less than 6, then log messages will be buffered. The buffered logs will be dumped to a log file when MIOpen logs an error message, or an error is thrown by MIOpen. This log can be found in /tmp/miopen_error_. From 9623a71489b5bce31fe7f4dc5e032ffbc071f0de Mon Sep 17 00:00:00 2001 From: Chris Erb Date: Thu, 15 Jan 2026 08:56:44 -0600 Subject: [PATCH 10/22] Apply suggestions from code review Co-authored-by: Matt Williams --- projects/miopen/CHANGELOG.md | 2 +- projects/miopen/docs/how-to/debug-log.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/miopen/CHANGELOG.md b/projects/miopen/CHANGELOG.md index 2dd7953f1ec5..47c7eb67c420 100644 --- a/projects/miopen/CHANGELOG.md +++ b/projects/miopen/CHANGELOG.md @@ -6,7 +6,7 @@ Full documentation for MIOpen is available [here](https://rocm.docs.amd.com/proj ### Added * New API entry-points `miopenBatchNormalizationForwardInferenceInvVariance` and `miopenBatchNormForwardInferenceActivationInvVariance` to support hipDNN. -* Log level Info2 dumped to file (/tmp/miopen_error_) on error log or MIOpen throw. +* Log level Info2 dumped to file (`/tmp/miopen_error_`) on error log or MIOpen throw. ### Optimized * Added `MIOPEN_SEARCH_CUTOFF` option which can reduce tuning times by skipping slow solvers and kernels diff --git a/projects/miopen/docs/how-to/debug-log.rst b/projects/miopen/docs/how-to/debug-log.rst index 8c69a23bdbe5..3a53fd9be5e5 100644 --- a/projects/miopen/docs/how-to/debug-log.rst +++ b/projects/miopen/docs/how-to/debug-log.rst @@ -52,7 +52,7 @@ environmental variables to control logging. Both variables are disabled by defau If ``MIOPEN_LOG_LEVEL`` is less than 6, then log messages will be buffered. The buffered logs will be dumped to a log file when MIOpen logs an error message, or an error is thrown by MIOpen. - This log can be found in /tmp/miopen_error_. + This log can be found in ``/tmp/miopen_error_``. .. note:: From 9ca0d36781b5cc5688b45d4fa3610d9d6a3e4bc9 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Thu, 15 Jan 2026 15:47:58 +0000 Subject: [PATCH 11/22] add hostname to log dump notification --- projects/miopen/src/logger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 3d634a8e705a..c9a0b322788e 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -82,7 +82,7 @@ void OutputBufferedLogs() { auto filename = fs::temp_directory_path() / ("miopen_error_" + std::to_string(getpid()) + ".log"); - std::cerr << "Buffered " << miopen::log_buffer_i << " messages to file: " << filename.string() + std::cerr << "Buffered " << miopen::log_buffer_i << " messages to file: " << sysinfo::GetSystemHostname() << ":"<< filename.string() << std::endl; auto err_file = std::ofstream{filename}; size_t i = miopen::log_buffer_i; From bcf774e40de3d5011cd4cbe967945f5806a61dea Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Thu, 22 Jan 2026 21:55:03 +0000 Subject: [PATCH 12/22] correction to log buffer index --- projects/miopen/src/include/miopen/logger.hpp | 45 +++++++++---------- projects/miopen/src/logger.cpp | 5 ++- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index 24449a56e06a..a1c6b4b7dae4 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -369,29 +369,28 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, #define MIOPEN_GET_FN_NAME miopen::LoggingParseFunction(__func__, __PRETTY_FUNCTION__) #endif -#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ - do \ - { \ - std::ostringstream miopen_log_ss; \ - miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ - << __VA_ARGS__ << std::endl; \ - if(miopen::IsLogging(level, disableQuieting)) \ - { \ - std::cerr << miopen_log_ss.str(); \ - } \ - if(!miopen::IsLogging(miopen::LoggingLevel::Info2, disableQuieting)) \ - { \ - if(level < miopen::LoggingLevel::Trace) \ - { \ - miopen::log_buffer[miopen::log_buffer_i % miopen::log_buffer_size] = \ - miopen_log_ss.str(); \ - miopen::log_buffer_i++; \ - } \ - if(level == miopen::LoggingLevel::Error) \ - { \ - miopen::OutputBufferedLogs(); \ - } \ - } \ +#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ + do \ + { \ + std::ostringstream miopen_log_ss; \ + miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ + << __VA_ARGS__ << std::endl; \ + if(miopen::IsLogging(level, disableQuieting)) \ + { \ + std::cerr << miopen_log_ss.str(); \ + } \ + if(!miopen::IsLogging(miopen::LoggingLevel::Info2, disableQuieting)) \ + { \ + if(level < miopen::LoggingLevel::Trace) \ + { \ + miopen::log_buffer[miopen::log_buffer_i] = miopen_log_ss.str(); \ + miopen::log_buffer_i = (miopen::log_buffer_i + 1) % miopen::log_buffer_size; \ + } \ + if(level == miopen::LoggingLevel::Error) \ + { \ + miopen::OutputBufferedLogs(); \ + } \ + } \ } while(false) #define MIOPEN_LOG_XQ_(level, disableQuieting, fn_name, ...) \ diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index c9a0b322788e..9e26809b1ddc 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -80,10 +80,11 @@ thread_local std::vector log_buffer(log_buffer_size, ""); void OutputBufferedLogs() { + auto buffer_size = (log_buffer[log_buffer_size - 1] == "") ? log_buffer_i : log_buffer_size; auto filename = fs::temp_directory_path() / ("miopen_error_" + std::to_string(getpid()) + ".log"); - std::cerr << "Buffered " << miopen::log_buffer_i << " messages to file: " << sysinfo::GetSystemHostname() << ":"<< filename.string() - << std::endl; + std::cerr << "Buffered " << buffer_size << " messages to file: " << sysinfo::GetSystemHostname() + << ":" << filename.string() << std::endl; auto err_file = std::ofstream{filename}; size_t i = miopen::log_buffer_i; do From 57c06fb87ad1972ff06c1960101c67c1a68c5b48 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Thu, 22 Jan 2026 22:52:51 +0000 Subject: [PATCH 13/22] clean includes --- projects/miopen/src/include/miopen/logger.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index a1c6b4b7dae4..aea6780af3be 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include From 21b0cbbb0826705eb6563370ad7ca668c9f5916e Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Fri, 23 Jan 2026 16:23:30 +0000 Subject: [PATCH 14/22] tidy --- projects/miopen/src/include/miopen/logger.hpp | 8 +++++--- projects/miopen/src/logger.cpp | 5 ++++- projects/miopen/test/gtest/log.cpp | 3 +-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index aea6780af3be..21fc5ca94ee3 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -138,9 +138,6 @@ namespace miopen { -extern thread_local size_t log_buffer_size, log_buffer_i; -extern thread_local std::vector log_buffer; - void OutputBufferedLogs(); template @@ -368,6 +365,11 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, #define MIOPEN_GET_FN_NAME miopen::LoggingParseFunction(__func__, __PRETTY_FUNCTION__) #endif +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +extern thread_local size_t log_buffer_size, log_buffer_i; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +extern thread_local std::vector log_buffer; + #define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ do \ { \ diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 9e26809b1ddc..770654d7da65 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -74,8 +74,11 @@ MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_BUFFER_SIZE, 128); namespace miopen { +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) thread_local size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); -thread_local size_t log_buffer_i = 0; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) +thread_local size_t log_buffer_i = 0; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) thread_local std::vector log_buffer(log_buffer_size, ""); void OutputBufferedLogs() diff --git a/projects/miopen/test/gtest/log.cpp b/projects/miopen/test/gtest/log.cpp index a4d390931c9c..1c5e49d13e43 100644 --- a/projects/miopen/test/gtest/log.cpp +++ b/projects/miopen/test/gtest/log.cpp @@ -375,7 +375,7 @@ void TestLogBufferOn() MIOPEN_LOG_I("info"); MIOPEN_LOG_I2("info2"); MIOPEN_LOG_T("trace"); - EXPECT_ANY_THROW(MIOPEN_THROW("throw")); + EXPECT_ANY_THROW({ MIOPEN_THROW("throw"); }); EXPECT_TRUE(fs::exists(filename)); log_file = std::ifstream{filename}; @@ -398,7 +398,6 @@ void TestLogBufferOff() { auto filename = fs::temp_directory_path() / ("miopen_error_" + std::to_string(getpid()) + ".log"); - std::string line; ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, "6"); // miopen::LoggingLevel::Info2 From b368c324650271099e005c8032edc7faee29ae06 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Fri, 23 Jan 2026 22:37:14 +0000 Subject: [PATCH 15/22] clear dump file for buffer test --- projects/miopen/test/gtest/log.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/projects/miopen/test/gtest/log.cpp b/projects/miopen/test/gtest/log.cpp index 1c5e49d13e43..1dac60545683 100644 --- a/projects/miopen/test/gtest/log.cpp +++ b/projects/miopen/test/gtest/log.cpp @@ -340,6 +340,8 @@ void TestLogBufferOn() size_t line_i = 0; std::string line; + fs::remove(filename); + ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, "5"); // miopen::LoggingLevel::Info // test log dump after error @@ -399,6 +401,8 @@ void TestLogBufferOff() auto filename = fs::temp_directory_path() / ("miopen_error_" + std::to_string(getpid()) + ".log"); + fs::remove(filename); + ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, "6"); // miopen::LoggingLevel::Info2 From f1440fa266fb7494bb04791c2f763248af2fd9b4 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Tue, 27 Jan 2026 14:09:41 -0600 Subject: [PATCH 16/22] global namespace for getpid --- projects/miopen/src/logger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 770654d7da65..57d678e9b231 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -85,7 +85,7 @@ void OutputBufferedLogs() { auto buffer_size = (log_buffer[log_buffer_size - 1] == "") ? log_buffer_i : log_buffer_size; auto filename = - fs::temp_directory_path() / ("miopen_error_" + std::to_string(getpid()) + ".log"); + fs::temp_directory_path() / ("miopen_error_" + std::to_string(::getpid()) + ".log"); std::cerr << "Buffered " << buffer_size << " messages to file: " << sysinfo::GetSystemHostname() << ":" << filename.string() << std::endl; auto err_file = std::ofstream{filename}; From a7d465da03f4e0e2cc8842fe7a4dd1b2e24922ab Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Tue, 27 Jan 2026 16:44:55 -0600 Subject: [PATCH 17/22] add getpid for win --- projects/miopen/src/logger.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 57d678e9b231..8aa14df16279 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -41,6 +41,14 @@ #include /* For SYS_xxx definitions */ #endif +#ifdef _WIN32 +#include +size_t getpid() +{ + return GetCurrentProcessId(); +} +#endif + /// Enable logging of the most important function calls. /// Name of envvar in a bit inadequate due to historical reasons. MIOPEN_DECLARE_ENV_VAR_BOOL(MIOPEN_ENABLE_LOGGING) From 8d30e923c144d2dfcc7d8dd4dfc717ff50e53fc7 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 28 Jan 2026 09:38:01 -0600 Subject: [PATCH 18/22] update log buffering functions --- projects/miopen/src/include/miopen/logger.hpp | 52 +++++++++---------- projects/miopen/src/logger.cpp | 21 ++++---- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index 21fc5ca94ee3..5546c4700309 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -138,8 +138,6 @@ namespace miopen { -void OutputBufferedLogs(); - template std::ostream& LogRange(std::ostream& os, Range&& r, std::string delim) { @@ -365,33 +363,31 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, #define MIOPEN_GET_FN_NAME miopen::LoggingParseFunction(__func__, __PRETTY_FUNCTION__) #endif -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -extern thread_local size_t log_buffer_size, log_buffer_i; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -extern thread_local std::vector log_buffer; +void BufferLog(std::string line); -#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ - do \ - { \ - std::ostringstream miopen_log_ss; \ - miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ - << __VA_ARGS__ << std::endl; \ - if(miopen::IsLogging(level, disableQuieting)) \ - { \ - std::cerr << miopen_log_ss.str(); \ - } \ - if(!miopen::IsLogging(miopen::LoggingLevel::Info2, disableQuieting)) \ - { \ - if(level < miopen::LoggingLevel::Trace) \ - { \ - miopen::log_buffer[miopen::log_buffer_i] = miopen_log_ss.str(); \ - miopen::log_buffer_i = (miopen::log_buffer_i + 1) % miopen::log_buffer_size; \ - } \ - if(level == miopen::LoggingLevel::Error) \ - { \ - miopen::OutputBufferedLogs(); \ - } \ - } \ +void OutputBufferedLogs(); + +#define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ + do \ + { \ + std::ostringstream miopen_log_ss; \ + miopen_log_ss << miopen::LoggingPrefix() << category << " [" << fn_name << "] " \ + << __VA_ARGS__ << std::endl; \ + if(miopen::IsLogging(level, disableQuieting)) \ + { \ + std::cerr << miopen_log_ss.str(); \ + } \ + if(!miopen::IsLogging(miopen::LoggingLevel::Info2, disableQuieting)) \ + { \ + if(level < miopen::LoggingLevel::Trace) \ + { \ + miopen::BufferLog(miopen_log_ss.str()); \ + } \ + if(level == miopen::LoggingLevel::Error) \ + { \ + miopen::OutputBufferedLogs(); \ + } \ + } \ } while(false) #define MIOPEN_LOG_XQ_(level, disableQuieting, fn_name, ...) \ diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 8aa14df16279..d3afbfce8161 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -43,10 +43,7 @@ #ifdef _WIN32 #include -size_t getpid() -{ - return GetCurrentProcessId(); -} +size_t getpid() { return GetCurrentProcessId(); } #endif /// Enable logging of the most important function calls. @@ -89,6 +86,12 @@ thread_local size_t log_buffer_i = 0; // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) thread_local std::vector log_buffer(log_buffer_size, ""); +void BufferLog(std::string line); +{ + log_buffer[log_buffer_i] = line; + log_buffer_i = (log_buffer_i + 1) % log_buffer_size; +} + void OutputBufferedLogs() { auto buffer_size = (log_buffer[log_buffer_size - 1] == "") ? log_buffer_i : log_buffer_size; @@ -97,15 +100,15 @@ void OutputBufferedLogs() std::cerr << "Buffered " << buffer_size << " messages to file: " << sysinfo::GetSystemHostname() << ":" << filename.string() << std::endl; auto err_file = std::ofstream{filename}; - size_t i = miopen::log_buffer_i; + size_t i = log_buffer_i; do { - if(miopen::log_buffer[i] != "") + if(log_buffer[i] != "") { - err_file << miopen::log_buffer[i]; + err_file << log_buffer[i]; } - i = (i + 1) % miopen::log_buffer_size; - } while(i != miopen::log_buffer_i); + i = (i + 1) % log_buffer_size; + } while(i != log_buffer_i); } namespace debug { From 2c62b97b23c8af3f7f221738df640361c2b0b8d1 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 28 Jan 2026 16:52:16 +0000 Subject: [PATCH 19/22] error fix --- projects/miopen/src/logger.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index d3afbfce8161..40458698f1eb 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -79,14 +79,11 @@ MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_BUFFER_SIZE, 128); namespace miopen { -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) -thread_local size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) -thread_local size_t log_buffer_i = 0; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) -thread_local std::vector log_buffer(log_buffer_size, ""); - -void BufferLog(std::string line); +static thread_local size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); +static thread_local size_t log_buffer_i = 0; +static thread_local std::vector log_buffer(log_buffer_size, ""); + +void BufferLog(std::string line) { log_buffer[log_buffer_i] = line; log_buffer_i = (log_buffer_i + 1) % log_buffer_size; From d56b20cb6cc44c11644500dcfad5b8c36baae479 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 28 Jan 2026 17:32:10 +0000 Subject: [PATCH 20/22] nolint --- projects/miopen/src/logger.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 40458698f1eb..03e2cff7ab31 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -79,8 +79,11 @@ MIOPEN_DECLARE_ENV_VAR_UINT64(MIOPEN_LOG_BUFFER_SIZE, 128); namespace miopen { +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) static thread_local size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) static thread_local size_t log_buffer_i = 0; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) static thread_local std::vector log_buffer(log_buffer_size, ""); void BufferLog(std::string line) From bc49ce2bd9bb7b27aa911fda3733e025e231294b Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Wed, 28 Jan 2026 19:37:59 +0000 Subject: [PATCH 21/22] add function to clear buffer --- projects/miopen/src/include/miopen/logger.hpp | 6 ++++-- projects/miopen/src/logger.cpp | 8 +++++++- projects/miopen/test/gtest/log.cpp | 9 +++------ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index 5546c4700309..da5ce69f9708 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -363,9 +363,11 @@ constexpr std::string_view LoggingParseFunction(const std::string_view func, #define MIOPEN_GET_FN_NAME miopen::LoggingParseFunction(__func__, __PRETTY_FUNCTION__) #endif -void BufferLog(std::string line); +MIOPEN_INTERNALS_EXPORT void ClearBufferLog(); -void OutputBufferedLogs(); +MIOPEN_INTERNALS_EXPORT void BufferLog(std::string line); + +MIOPEN_INTERNALS_EXPORT void OutputBufferedLogs(); #define MIOPEN_LOG_XQ_CUSTOM(level, disableQuieting, category, fn_name, ...) \ do \ diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index 03e2cff7ab31..d24e9ea575c2 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -82,10 +82,16 @@ namespace miopen { // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) static thread_local size_t log_buffer_size = env::value(MIOPEN_LOG_BUFFER_SIZE); // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) -static thread_local size_t log_buffer_i = 0; +static thread_local size_t log_buffer_i = 0; // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) static thread_local std::vector log_buffer(log_buffer_size, ""); +void ClearBufferLog() +{ + log_buffer_i = 0; + log_buffer = std::vector(miopen::log_buffer_size, ""); +} + void BufferLog(std::string line) { log_buffer[log_buffer_i] = line; diff --git a/projects/miopen/test/gtest/log.cpp b/projects/miopen/test/gtest/log.cpp index 1dac60545683..6fb6c0cad4e9 100644 --- a/projects/miopen/test/gtest/log.cpp +++ b/projects/miopen/test/gtest/log.cpp @@ -345,8 +345,7 @@ void TestLogBufferOn() ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, "5"); // miopen::LoggingLevel::Info // test log dump after error - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + miopen::ClearBufferLog(); MIOPEN_LOG_W("warn"); MIOPEN_LOG_I("info"); MIOPEN_LOG_I2("info2"); @@ -371,8 +370,7 @@ void TestLogBufferOn() fs::remove(filename); // test log dump after throw - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + miopen::ClearBufferLog(); MIOPEN_LOG_W("warn"); MIOPEN_LOG_I("info"); MIOPEN_LOG_I2("info2"); @@ -406,8 +404,7 @@ void TestLogBufferOff() ScopedEnvironment log_level_env(MIOPEN_LOG_LEVEL, "6"); // miopen::LoggingLevel::Info2 - miopen::log_buffer_i = 0; - miopen::log_buffer = std::vector(miopen::log_buffer_size, ""); + miopen::ClearBufferLog(); // log messages MIOPEN_LOG_W("warn"); MIOPEN_LOG_I("info"); From ebb0b06dccfe2be2d15bbea72cefb496715048f8 Mon Sep 17 00:00:00 2001 From: Christopher Erb Date: Thu, 5 Feb 2026 09:49:02 -0600 Subject: [PATCH 22/22] add test corrections for windows --- projects/miopen/src/include/miopen/logger.hpp | 4 ++ projects/miopen/src/logger.cpp | 2 +- projects/miopen/test/gtest/log.cpp | 45 ++++++++++--------- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/projects/miopen/src/include/miopen/logger.hpp b/projects/miopen/src/include/miopen/logger.hpp index da5ce69f9708..a1eb82f81aa0 100644 --- a/projects/miopen/src/include/miopen/logger.hpp +++ b/projects/miopen/src/include/miopen/logger.hpp @@ -41,6 +41,10 @@ #include #endif +#ifdef _WIN32 +MIOPEN_INTERNALS_EXPORT size_t getpid(); +#endif + // See https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms #define MIOPEN_PP_CAT(x, y) MIOPEN_PP_PRIMITIVE_CAT(x, y) #define MIOPEN_PP_PRIMITIVE_CAT(x, y) x##y diff --git a/projects/miopen/src/logger.cpp b/projects/miopen/src/logger.cpp index d24e9ea575c2..5b7169241fe6 100644 --- a/projects/miopen/src/logger.cpp +++ b/projects/miopen/src/logger.cpp @@ -43,7 +43,7 @@ #ifdef _WIN32 #include -size_t getpid() { return GetCurrentProcessId(); } +size_t getpid() { return _getpid(); } #endif /// Enable logging of the most important function calls. diff --git a/projects/miopen/test/gtest/log.cpp b/projects/miopen/test/gtest/log.cpp index 6fb6c0cad4e9..7ccb34e4c7f2 100644 --- a/projects/miopen/test/gtest/log.cpp +++ b/projects/miopen/test/gtest/log.cpp @@ -351,21 +351,24 @@ void TestLogBufferOn() MIOPEN_LOG_I2("info2"); MIOPEN_LOG_T("trace"); MIOPEN_LOG_E("error"); + ASSERT_TRUE(fs::exists(filename)); - auto log_file = std::ifstream{filename}; - while(std::getline(log_file, line)) { - switch(line_i) + auto log_file = std::ifstream{filename}; + while(std::getline(log_file, line)) { - case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; - case 1: ASSERT_TRUE(isSubStr(line, "info")); break; - case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; - case 3: - ASSERT_FALSE(isSubStr(line, "trace")); - ASSERT_TRUE(isSubStr(line, "error")); - break; + switch(line_i) + { + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: + ASSERT_FALSE(isSubStr(line, "trace")); + ASSERT_TRUE(isSubStr(line, "error")); + break; + } + line_i++; } - line_i++; } fs::remove(filename); @@ -378,18 +381,20 @@ void TestLogBufferOn() EXPECT_ANY_THROW({ MIOPEN_THROW("throw"); }); EXPECT_TRUE(fs::exists(filename)); - log_file = std::ifstream{filename}; - line_i = 0; - while(std::getline(log_file, line)) { - switch(line_i) + auto log_file = std::ifstream{filename}; + line_i = 0; + while(std::getline(log_file, line)) { - case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; - case 1: ASSERT_TRUE(isSubStr(line, "info")); break; - case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; - case 3: ASSERT_TRUE(isSubStr(line, "throw")); break; + switch(line_i) + { + case 0: ASSERT_TRUE(isSubStr(line, "warn")); break; + case 1: ASSERT_TRUE(isSubStr(line, "info")); break; + case 2: ASSERT_TRUE(isSubStr(line, "info2")); break; + case 3: ASSERT_TRUE(isSubStr(line, "throw")); break; + } + line_i++; } - line_i++; } fs::remove(filename); }