From b4691c81c9f89abb707c652aeefaa7020c046339 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Thu, 21 Nov 2024 09:48:05 -0800 Subject: [PATCH 01/14] start moved to unified logging lib --- src/libs/CMakeLists.txt | 9 +- src/libs/ascent/CMakeLists.txt | 5 +- src/libs/logging/CMakeLists.txt | 45 +++ .../utils => logging}/ascent_annotations.cpp | 16 +- .../utils => logging}/ascent_annotations.hpp | 7 +- src/libs/logging/ascent_logging.cpp | 288 ++++++++++++++++++ src/libs/logging/ascent_logging.hpp | 265 ++++++++++++++++ src/libs/logging/ascent_logging_exports.h | 45 +++ src/tests/CMakeLists.txt | 3 + src/tests/logging/CMakeLists.txt | 27 ++ src/tests/logging/t_ascent_logger_basic.cpp | 51 ++++ 11 files changed, 745 insertions(+), 16 deletions(-) create mode 100644 src/libs/logging/CMakeLists.txt rename src/libs/{ascent/utils => logging}/ascent_annotations.cpp (90%) rename src/libs/{ascent/utils => logging}/ascent_annotations.hpp (97%) create mode 100644 src/libs/logging/ascent_logging.cpp create mode 100644 src/libs/logging/ascent_logging.hpp create mode 100644 src/libs/logging/ascent_logging_exports.h create mode 100644 src/tests/logging/CMakeLists.txt create mode 100644 src/tests/logging/t_ascent_logger_basic.cpp diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt index e42a92e89..26177be3f 100644 --- a/src/libs/CMakeLists.txt +++ b/src/libs/CMakeLists.txt @@ -8,7 +8,6 @@ ################################ add_subdirectory(flow) - # display info about optional features if(ENABLE_APCOMP) message(STATUS "Building APComp (ENABLE_APCOMP=ON)") @@ -29,10 +28,18 @@ else() endif() +################################ # ascent_png_utils object lib # shared for testing of all libs +################################ add_subdirectory(png_utils) +################################ +# ascent_logging lib +# shared logging for all libs +################################ +add_subdirectory(logging) + ################################ # Add ap comp ################################ diff --git a/src/libs/ascent/CMakeLists.txt b/src/libs/ascent/CMakeLists.txt index 7c41d157a..730dd6744 100644 --- a/src/libs/ascent/CMakeLists.txt +++ b/src/libs/ascent/CMakeLists.txt @@ -179,7 +179,6 @@ set(ascent_headers utils/ascent_resources.hpp utils/ascent_resources_cinema_web.hpp utils/ascent_resources_ascent_web.hpp - utils/ascent_annotations.hpp # hola hola/ascent_hola.hpp) @@ -243,7 +242,6 @@ set(ascent_sources utils/ascent_string_utils.cpp utils/ascent_web_interface.cpp utils/ascent_resources.cpp - utils/ascent_annotations.cpp # hola hola/ascent_hola.cpp) @@ -371,7 +369,8 @@ set(ascent_thirdparty_libs conduit::conduit ascent_flow ascent_lodepng - ascent_png_utils) + ascent_png_utils + ascent_logging) ################## # optional libs diff --git a/src/libs/logging/CMakeLists.txt b/src/libs/logging/CMakeLists.txt new file mode 100644 index 000000000..d68127729 --- /dev/null +++ b/src/libs/logging/CMakeLists.txt @@ -0,0 +1,45 @@ +# Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +# Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +# other details. No copyright assignment is required to contribute to Ascent. + +set(ascent_logging_headers + ascent_logging.hpp + ascent_annotations.hpp + ascent_logging_exports.h + ) + +set(ascent_logging_sources + ascent_logging.cpp + ascent_annotations.cpp + ) + + +set(ascent_logging_deps conduit::conduit) + +if(CALIPER_FOUND) + list(APPEND ascent_logging_deps caliper) +endif() + +blt_add_library(NAME ascent_logging + SOURCES ${ascent_logging_sources} + HEADERS ${aascent_logging_headers} + DEPENDS_ON ${ascent_logging_deps}) + +target_include_directories(ascent_logging PUBLIC $) + +# extra defs and props +target_compile_definitions(ascent_logging PUBLIC ASCENT_LOGGING_ENABLE_CALIPER) +target_compile_definitions(ascent_logging PRIVATE ASCENT_EXPORTS_FLAG) + +if(ENABLE_HIDDEN_VISIBILITY) + set_target_properties(ascent_logging PROPERTIES CXX_VISIBILITY_PRESET hidden) +endif() + +install(FILES ${ascent_logging_headers} DESTINATION include/ascent/) + +install(TARGETS ascent_logging + EXPORT ascent + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION lib + ) diff --git a/src/libs/ascent/utils/ascent_annotations.cpp b/src/libs/logging/ascent_annotations.cpp similarity index 90% rename from src/libs/ascent/utils/ascent_annotations.cpp rename to src/libs/logging/ascent_annotations.cpp index 196cabae4..3ab4ea384 100644 --- a/src/libs/ascent/utils/ascent_annotations.cpp +++ b/src/libs/logging/ascent_annotations.cpp @@ -15,7 +15,7 @@ //----------------------------------------------------------------------------- #include "conduit.hpp" -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) #include "caliper/cali-manager.h" #endif @@ -31,7 +31,7 @@ namespace ascent namespace annotations { -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) static cali::ConfigManager *cali_cfg_manager = NULL; #endif @@ -40,7 +40,7 @@ static cali::ConfigManager *cali_cfg_manager = NULL; bool supported() { -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) return true; #else return false; @@ -51,7 +51,7 @@ supported() void initialize() { -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) conduit::Node opts; initialize(opts); #endif @@ -61,11 +61,11 @@ initialize() void initialize(const conduit::Node &opts) { -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) if(cali_cfg_manager != NULL) { - ASCENT_ERROR("Ascent Caliper Config Manager already initialized.") + ASCENT_LOG_ERROR("Ascent Caliper Config Manager already initialized.") } // check opts @@ -113,7 +113,7 @@ initialize(const conduit::Node &opts) void flush() { -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) if(cali_cfg_manager != NULL) { cali_cfg_manager->flush(); @@ -126,7 +126,7 @@ flush() void finalize() { -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) flush(); if(cali_cfg_manager != NULL) { diff --git a/src/libs/ascent/utils/ascent_annotations.hpp b/src/libs/logging/ascent_annotations.hpp similarity index 97% rename from src/libs/ascent/utils/ascent_annotations.hpp rename to src/libs/logging/ascent_annotations.hpp index 7017f1bad..69dcd4743 100644 --- a/src/libs/ascent/utils/ascent_annotations.hpp +++ b/src/libs/logging/ascent_annotations.hpp @@ -14,12 +14,11 @@ //----------------------------------------------------------------------------- // -- ascent includes -- //----------------------------------------------------------------------------- -#include -#include +#include #include //----------------------------------------------------------------------------- -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) #include #endif @@ -28,7 +27,7 @@ /// ASCENT_ANNOTATE_ZZZ macros are used for caliper performance annotations. // //----------------------------------------------------------------------------- -#if defined(ASCENT_CALIPER_ENABLED) +#if defined(ASCENT_LOGGING_ENABLE_CALIPER) #define ASCENT_ANNOTATE_MARK_BEGIN( name ) CALI_MARK_BEGIN( name ) #define ASCENT_ANNOTATE_MARK_END( name ) CALI_MARK_END( name ) #define ASCENT_ANNOTATE_MARK_FUNCTION CALI_CXX_MARK_FUNCTION diff --git a/src/libs/logging/ascent_logging.cpp b/src/libs/logging/ascent_logging.cpp new file mode 100644 index 000000000..3cd942ffe --- /dev/null +++ b/src/libs/logging/ascent_logging.cpp @@ -0,0 +1,288 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +//----------------------------------------------------------------------------- +/// +/// file: ascent_logging.cpp +/// +//----------------------------------------------------------------------------- + +#include "ascent_logging.hpp" + +// standard includes +#include + +#include +#include +#include + +// thirdparty includes +#include +#include + +using namespace conduit; + +//----------------------------------------------------------------------------- +// -- begin ascent:: -- +//----------------------------------------------------------------------------- +namespace ascent +{ + +Logger *Logger::m_active_logger = nullptr; +std::map Logger::m_loggers; +std::vector Logger::m_level_strings = {"unset", + "debug", + "info", + "warn", + "error", + "legendary"}; + +//----------------------------------------------------------------------------- +Logger::Scope::Scope(Logger *lgr, const std::string &name) + : m_lgr(lgr), + m_name(name) +{ + if(m_lgr != nullptr) + { + m_lgr->log_block_begin(m_name); + } +} + +//----------------------------------------------------------------------------- +Logger::Scope::~Scope() +{ + if(m_lgr != nullptr) + { + m_lgr->log_block_end(m_name); + } +} + + +//----------------------------------------------------------------------------- +Logger::Logger() + : m_indent_level(0), + m_rank(-1), + m_level_threshold(INFO), + m_echo_level_threshold(LEGENDARY) +{} + +//----------------------------------------------------------------------------- +Logger::~Logger() +{ + close(); +} + +//----------------------------------------------------------------------------- +void +Logger::open(const std::string &ofpattern) +{ + // multi node case, assumes file pattern includes "rank" + std::string ofname; + if(rank() > -1) + { + ofname = conduit_fmt::format(ofpattern, + conduit_fmt::arg("rank",rank())); + } + else + { + ofname = ofpattern; + } + + m_ofstream.open(ofname.c_str()); + + if(!m_ofstream.is_open()) + { + std::cerr << "[ERROR] Failed to open log file: " << ofname << std::endl; + } +} + + +//----------------------------------------------------------------------------- +void +Logger::close() +{ + if(m_ofstream.is_open()) + { + m_ofstream.close(); + } +} + +//----------------------------------------------------------------------------- +void +Logger::flush() +{ + m_ofstream << std::flush; +} + +//----------------------------------------------------------------------------- +void +Logger::log_block_begin(const std::string &name) +{ + stream() << m_indent_string << name << ":\n"; + set_indent_level(indent_level()+1); +} + +//----------------------------------------------------------------------------- +void +Logger::log_block_end(const std::string &name) +{ + set_indent_level(indent_level()-1); +} + +//----------------------------------------------------------------------------- +void +Logger::log_message(int level, + const std::string &msg, + const std::string &file, + int line) +{ + /* + {parent_indent}- + {parent_indent}{indent}level: + {parent_indent}{indent}file: + {parent_indent}{indent}line: + ... msg txt + */ + stream() << m_indent_string <<"-\n"; + stream() << m_indent_string << " level: " << level_string(level) << "\n"; + stream() << m_indent_string << " file: " << file << "\n"; + stream() << m_indent_string << " line: " << line << "\n"; + log_message_inner(msg); +} + +//----------------------------------------------------------------------------- +void +Logger::log_message(int level, + const std::string &msg) +{ + /* + {parent_indent}- + {parent_indent}{indent}level: + ... msg txt + */ + stream() << m_indent_string <<"-\n"; + stream() << m_indent_string << " level: " << level_string(level) << "\n"; + log_message_inner(msg); +} + + +//----------------------------------------------------------------------------- +void +Logger::log_message_inner(const std::string &msg) +{ + /* + {parent_indent}{indent}msg: | + {parent_indent}{indent}{indent} msg line + ... + {parent_indent}{indent}{indent} msg line + */ + stream() << m_indent_string << " msg: |\n"; + std::istringstream input; + input.str(msg); + for (std::string line; std::getline(input, line);) + { + stream() << m_indent_string << " " << line << "\n"; + } +} + +//----------------------------------------------------------------------------- +int +Logger::indent_level() const +{ + return m_indent_level; +} + +//----------------------------------------------------------------------------- +void +Logger::set_indent_level(int level) +{ + m_indent_level = level; + m_indent_string = std::string(m_indent_level*2, ' '); +} + +//----------------------------------------------------------------------------- +int +Logger::rank() const +{ + return m_rank; +} + +//----------------------------------------------------------------------------- +void +Logger::set_level_threshold(int level) +{ + m_level_threshold = level; +} + +//----------------------------------------------------------------------------- +int +Logger::level_threshold() const +{ + return m_level_threshold; +} + +//----------------------------------------------------------------------------- +void +Logger::set_echo_level_threshold(int level) +{ + m_echo_level_threshold = level; +} + +//----------------------------------------------------------------------------- +int +Logger::echo_level_threshold() const +{ + return m_echo_level_threshold; +} + +//----------------------------------------------------------------------------- +std::ostream & +Logger::stream() +{ + return m_ofstream; +} + +//----------------------------------------------------------------------------- +Logger * +Logger::active_instance() +{ + return m_active_logger; +} + +//----------------------------------------------------------------------------- +Logger * +Logger::activate_instance(const std::string &ofile_pattern) +{ + m_active_logger = &m_loggers[ofile_pattern]; + return m_active_logger; +} + +//----------------------------------------------------------------------------- +const std::string & +Logger::level_string(int level) +{ + if(level < Logger::UNKNOWN ) + { + level = Logger::UNKNOWN; + } + else if(level > Logger::LEGENDARY) + { + level = Logger::LEGENDARY; + } + return m_level_strings[level]; +} + + + +//----------------------------------------------------------------------------- +}; +//----------------------------------------------------------------------------- +// -- end ascent:: -- +//----------------------------------------------------------------------------- + + + + diff --git a/src/libs/logging/ascent_logging.hpp b/src/libs/logging/ascent_logging.hpp new file mode 100644 index 000000000..f1d55dc87 --- /dev/null +++ b/src/libs/logging/ascent_logging.hpp @@ -0,0 +1,265 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +//----------------------------------------------------------------------------- +/// +/// file: ascent_logging.hpp +/// +//----------------------------------------------------------------------------- +#ifndef ASCENT_LOGGING_HPP +#define ASCENT_LOGGING_HPP + +#include +#include + +#include +#include + +/* +ASCENT_LOG_OPEN( output_file_name_pattern ) // serial +ASCENT_LOG_OPEN( output_file_name_pattern, rank ) // mpi par + +ASCENT_LOG_DEBUG( msg ) (w/ line, file, etc) +ASCENT_LOG_INFO( msg ) (w/ line, file, etc) +ASCENT_LOG_WARN( msg ) (w/ line, file, etc) +ASCENT_LOG_ERROR( msg ) (w/ line, file, etc) + +ASCENT_LOG_SCOPE( name ) --> increase indent +ASCENT_LOG_MARK_BEGIN( name ) --> increase indent +ASCENT_LOG_MARK_END( name ) --> decrease indent +ASCENT_LOG_MARK_FUNCTION () + +ASCENT_LOG_FLUSH() +*/ + +//----------------------------------------------------------------------------- +#define ASCENT_LOG_OPEN( ofname_pattern ) \ +{ \ + ascent::Logger *lgr = ascent::Logger::activate_instance(ofname_pattern); \ + lgr->open(ofname_pattern); \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_LOG_OPEN_RANK( ofname_pattern , rank ) \ +{ \ + ascent::Logger *lgr = ascent::Logger::activate_instance(ofname_pattern); \ + lgr->set_rank(rank); \ + lgr->open(ofname_pattern); \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_LOG_ACTIVATE( ofname_pattern ) \ +{ \ + Logger::activate_instance(ofname_pattern); \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_LOG_DEBUG( msg ) \ +{ \ + ascent::Logger *_ascent_lgr = Logger::active_instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + _ascent_lgr->log_message(ascent::Logger::DEBUG, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ + } \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_LOG_INFO( msg ) \ +{ \ + ascent::Logger *_ascent_lgr = Logger::active_instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + _ascent_lgr->log_message(ascent::Logger::INFO, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ + } \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_LOG_WARN( msg ) \ +{ \ + ascent::Logger *_ascent_lgr = Logger::active_instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + _ascent_lgr->log_message(ascent::Logger::WARN, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ + } \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_LOG_ERROR( msg ) \ +{ \ + ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + _ascent_lgr->log_message(ascent::Logger::ERROR, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ + } \ +}// TODO EXCEPTION! + +//----------------------------------------------------------------------------- +#define ASCENT_FLUSH () \ +{ \ + ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + _ascent_lgr->flush(); \ + } \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_MARK_SCOPE( name ) ASCENT_ANNOTATE_MARK_SCOPE; ascent::Logger::Scope _ascent_lgr_scope(ascent::Logger::active_instance(), name ); + +//----------------------------------------------------------------------------- +#define ASCENT_MARK_FUNCTION( name ) ASCENT_ANNOTATE_MARK_FUNCTION; ascent::Logger::Scope _ascent_lgr_func(ascent::Logger::active_instance(), std::string(__func__)); + +//----------------------------------------------------------------------------- +#define ASCENT_MARK_BEGIN( name ) ASCENT_ANNOTATE_MARK_BEGIN( name ); \ +{ \ + ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + _ascent_lgr->log_block_begin(name); \ + } \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_MARK_END( name ) ASCENT_ANNOTATE_MARK_END( name ); \ +{ \ + ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + _ascent_lgr->log_block_end(name); \ + } \ +} + + +//----------------------------------------------------------------------------- +// -- begin ascent:: -- +//----------------------------------------------------------------------------- +namespace ascent +{ + +//----------------------------------------------------------------------------- +class ASCENT_API Logger +{ +public: + + //------------------------------------------------------------------------- + typedef enum + { + UNKNOWN = -1, + DEBUG = 1, + INFO = 2, + WARN = 3, + ERROR = 4, + LEGENDARY = 5, + } MessageLevel; + + //------------------------------------------------------------------------- + class ASCENT_API Scope + { + public: + Scope(Logger *lgr, const std::string &name); + ~Scope(); + private: + Logger *m_lgr; + std::string m_name; + }; + + //------------------------------------------------------------------------- + Logger(); + ~Logger(); + + // + // "ascent_log_out.yaml" + // "ascent_log_out_{rank}.yaml" + // "ascent_log_out_{rank:05d}.yaml" + // + + void open(const std::string &ofile_pattern); + + void close(); + void flush(); + + void log_message(int level, + const std::string &msg, + const std::string &file, + int line); + + void log_message(int level, + const std::string &msg); + void log_block_begin(const std::string &name); + void log_block_end(const std::string &name); + + int rank() const; + void set_rank(int rank); + + int indent_level() const; + void set_indent_level(int level); + + // any msgs >= level_threshold will be logged + void set_level_threshold(int level); + int level_threshold() const; + + // any msgs >= echo_level_threshold will sent to std out as well as log + void set_echo_level_threshold(int level); + int echo_level_threshold() const; + + + std::ostream &stream(); + + static Logger *active_instance(); + static Logger *activate_instance(const std::string &ofile_pattern); + +private: + static const std::string &level_string(int level); + + void log_message_inner(const std::string &msg); + + std::ofstream m_ofstream; + + int m_indent_level; // default = 0 + int m_indent_spaces; // default = 4 + int m_rank; // default = -1 + int m_level_threshold; // default = INFO + int m_echo_level_threshold; // default = LEGENDARY + + std::string m_indent_string; // current indent string + + static Logger *m_active_logger; // default = nullptr + static std::map m_loggers; + static std::vector m_level_strings; +}; + +//----------------------------------------------------------------------------- +}; +//----------------------------------------------------------------------------- +// -- end ascent:: -- +//----------------------------------------------------------------------------- + +#endif +//----------------------------------------------------------------------------- +// -- end header ifdef guard +//----------------------------------------------------------------------------- + + diff --git a/src/libs/logging/ascent_logging_exports.h b/src/libs/logging/ascent_logging_exports.h new file mode 100644 index 000000000..b157f620d --- /dev/null +++ b/src/libs/logging/ascent_logging_exports.h @@ -0,0 +1,45 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + + +//----------------------------------------------------------------------------- +/// +/// file: ascent_logging_exports.h +/// +//----------------------------------------------------------------------------- + +#ifndef ASCENT_LOGGING_EXPORTS_H +#define ASCENT_LOGGING_EXPORTS_H + +//----------------------------------------------------------------------------- +// -- define proper lib exports for various platforms -- +//----------------------------------------------------------------------------- +#if defined(_WIN32) +#if defined(ASCENT_EXPORTS_FLAG) +#define ASCENT_API __declspec(dllexport) +#else +#define ASCENT_API __declspec(dllimport) +#endif +#if defined(_MSC_VER) +// Turn off warning about lack of DLL interface +#pragma warning(disable:4251) +// Turn off warning non-dll class is base for dll-interface class. +#pragma warning(disable:4275) +// Turn off warning about identifier truncation +#pragma warning(disable:4786) +#endif +#else +# if __GNUC__ >= 4 && defined(ASCENT_EXPORTS_FLAG) +# define ASCENT_API __attribute__ ((visibility("default"))) +# else +# define ASCENT_API /* hidden by default */ +# endif +#endif + +#endif + + + diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index a961ce81f..8708e9d5b 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -39,6 +39,9 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/vtkh") # add tpl smoke tests, so they run before we run the ascent tests add_subdirectory("thirdparty") +# add logging tests +add_subdirectory("logging") + # add apcomp tests if(ENABLE_APCOMP) add_subdirectory("apcomp") diff --git a/src/tests/logging/CMakeLists.txt b/src/tests/logging/CMakeLists.txt new file mode 100644 index 000000000..5ac0b6a22 --- /dev/null +++ b/src/tests/logging/CMakeLists.txt @@ -0,0 +1,27 @@ +############################################################################### +# Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +# Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +# other details. No copyright assignment is required to contribute to Ascent. +############################################################################### + + +################################ +# Unit Tests +################################ +set(BASIC_TESTS t_ascent_logger_basic) +# set(MPI_TESTS t_ascent_logger_mpi) + + +message(STATUS "Adding logger unit tests") +foreach(TEST ${BASIC_TESTS}) + message(STATUS "adding test ${TEST}") + add_cpp_test(TEST ${TEST} DEPENDS_ON ascent_logging) +endforeach() + +# if(MPI_FOUND) +# message(STATUS "Adding logger mpi unit tests") +# foreach(TEST ${MPI_TESTS}) +# message(STATUS "adding MPI test ${TEST}") +# add_cpp_mpi_test(TEST ${TEST} NUM_MPI_TASKS 2 DEPENDS_ON ascent_logging) +# endforeach() +# endif() diff --git a/src/tests/logging/t_ascent_logger_basic.cpp b/src/tests/logging/t_ascent_logger_basic.cpp new file mode 100644 index 000000000..85791e01f --- /dev/null +++ b/src/tests/logging/t_ascent_logger_basic.cpp @@ -0,0 +1,51 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +//----------------------------------------------------------------------------- +/// +/// file: t_ascent_logger_basic.cpp +/// +//----------------------------------------------------------------------------- + +#include "gtest/gtest.h" + +#include + +#include +#include + +#include "t_config.hpp" + +using namespace std; +using namespace conduit; +using namespace ascent; + +//----------------------------------------------------------------------------- +void myfunc() +{ + ASCENT_MARK_FUNCTION(); + ASCENT_LOG_INFO("I am here!"); +} + +//----------------------------------------------------------------------------- +TEST(ascent_smoke, ascent_about) +{ + ASCENT_LOG_OPEN("here_we_go.yaml") + ASCENT_LOG_INFO("my info!"); + ASCENT_LOG_WARN("my warning!"); + ASCENT_LOG_ERROR("my error!"); + ASCENT_MARK_BEGIN("blocky"); + ASCENT_LOG_INFO("my info!"); + ASCENT_LOG_WARN("my warning!"); + ASCENT_LOG_ERROR("my error!"); + ASCENT_MARK_END("blocky"); + myfunc(); + + ASCENT_MARK_BEGIN("blocky2"); + myfunc(); + ASCENT_MARK_END("blocky2"); +} + From 1ab134ab76c047b11b3e4ef47c2761fe95c3bef1 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Thu, 21 Nov 2024 15:52:57 -0800 Subject: [PATCH 02/14] new core logging lib --- src/libs/CMakeLists.txt | 13 +- src/libs/logging/CMakeLists.txt | 2 + src/libs/logging/ascent_logging.cpp | 161 ++++++++++++++++---- src/libs/logging/ascent_logging.hpp | 110 ++++++++----- src/libs/logging/ascent_logging_timer.cpp | 61 ++++++++ src/libs/logging/ascent_logging_timer.hpp | 56 +++++++ src/tests/logging/t_ascent_logger_basic.cpp | 82 +++++++++- 7 files changed, 409 insertions(+), 76 deletions(-) create mode 100644 src/libs/logging/ascent_logging_timer.cpp create mode 100644 src/libs/logging/ascent_logging_timer.hpp diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt index 26177be3f..49be02e31 100644 --- a/src/libs/CMakeLists.txt +++ b/src/libs/CMakeLists.txt @@ -2,13 +2,9 @@ # Project developers. See top-level LICENSE AND COPYRIGHT files for dates and # other details. No copyright assignment is required to contribute to Ascent. - -################################ -# Add flow -################################ -add_subdirectory(flow) - +####################################### # display info about optional features +####################################### if(ENABLE_APCOMP) message(STATUS "Building APComp (ENABLE_APCOMP=ON)") else() @@ -40,6 +36,11 @@ add_subdirectory(png_utils) ################################ add_subdirectory(logging) +################################ +# Add flow +################################ +add_subdirectory(flow) + ################################ # Add ap comp ################################ diff --git a/src/libs/logging/CMakeLists.txt b/src/libs/logging/CMakeLists.txt index d68127729..0d93cd9d1 100644 --- a/src/libs/logging/CMakeLists.txt +++ b/src/libs/logging/CMakeLists.txt @@ -4,12 +4,14 @@ set(ascent_logging_headers ascent_logging.hpp + ascent_logging_timer.hpp ascent_annotations.hpp ascent_logging_exports.h ) set(ascent_logging_sources ascent_logging.cpp + ascent_logging_timer.cpp ascent_annotations.cpp ) diff --git a/src/libs/logging/ascent_logging.cpp b/src/libs/logging/ascent_logging.cpp index 3cd942ffe..d16cf1613 100644 --- a/src/libs/logging/ascent_logging.cpp +++ b/src/libs/logging/ascent_logging.cpp @@ -31,8 +31,8 @@ using namespace conduit; namespace ascent { -Logger *Logger::m_active_logger = nullptr; -std::map Logger::m_loggers; +Logger Logger::m_instance; +Logger *Logger::m_active_instance = nullptr; std::vector Logger::m_level_strings = {"unset", "debug", "info", @@ -60,14 +60,15 @@ Logger::Scope::~Scope() } } - //----------------------------------------------------------------------------- Logger::Logger() : m_indent_level(0), m_rank(-1), m_level_threshold(INFO), m_echo_level_threshold(LEGENDARY) -{} +{ + m_key_counters.push(std::map()); +} //----------------------------------------------------------------------------- Logger::~Logger() @@ -84,7 +85,7 @@ Logger::open(const std::string &ofpattern) if(rank() > -1) { ofname = conduit_fmt::format(ofpattern, - conduit_fmt::arg("rank",rank())); + conduit_fmt::arg("rank",rank())); } else { @@ -99,6 +100,12 @@ Logger::open(const std::string &ofpattern) } } +//----------------------------------------------------------------------------- +bool +Logger::is_open() +{ + return m_ofstream.is_open(); +} //----------------------------------------------------------------------------- void @@ -121,15 +128,37 @@ Logger::flush() void Logger::log_block_begin(const std::string &name) { - stream() << m_indent_string << name << ":\n"; + // make sure we have a unique key name + + int key_count = m_key_counters.top()[name]++; + + stream() << m_indent_string <<"-\n"; + set_indent_level(indent_level()+1); + + if(key_count == 0) + { + stream() << m_indent_string << name << ":\n"; + } + else + { + stream() << m_indent_string << name << "_" << key_count <<":\n"; + } set_indent_level(indent_level()+1); + // add timer for new level + m_timers.push(Timer()); + // add key counter for new level + m_key_counters.push(std::map()); } //----------------------------------------------------------------------------- void Logger::log_block_end(const std::string &name) { - set_indent_level(indent_level()-1); + stream() << m_indent_string <<"-\n"; + stream() << m_indent_string << " time_elapsed: " << m_timers.top().elapsed() << "\n"; + set_indent_level(indent_level()-2); + m_key_counters.pop(); + m_timers.pop(); } //----------------------------------------------------------------------------- @@ -138,6 +167,29 @@ Logger::log_message(int level, const std::string &msg, const std::string &file, int line) +{ + // log if equal or above logging threshold + if(level >= log_threshold()) + { + log_message(level, msg, file, line, stream(), true); + } + + // echo if equal or above echo threshold + if(level >= echo_threshold()) + { + log_message(level, msg, file, line, std::cout, false); + } +} + + +//----------------------------------------------------------------------------- +void +Logger::log_message(int level, + const std::string &msg, + const std::string &file, + int line, + std::ostream &os, + bool detailed) { /* {parent_indent}- @@ -146,32 +198,61 @@ Logger::log_message(int level, {parent_indent}{indent}line: ... msg txt */ - stream() << m_indent_string <<"-\n"; - stream() << m_indent_string << " level: " << level_string(level) << "\n"; - stream() << m_indent_string << " file: " << file << "\n"; - stream() << m_indent_string << " line: " << line << "\n"; - log_message_inner(msg); + os << m_indent_string <<"-\n"; + os << m_indent_string << " level: " << level_string(level) << "\n"; + if(detailed) + { + os << m_indent_string << " file: " << file << "\n"; + os << m_indent_string << " line: " << line << "\n"; + os << m_indent_string << " timestamp: \"" << timestamp() << "\"\n"; + } + log_message_inner(msg, os); } //----------------------------------------------------------------------------- void Logger::log_message(int level, const std::string &msg) +{ + // log if equal or above logging threshold + if(level >= log_threshold()) + { + log_message(level, msg, stream(), true); + } + + // echo if equal or above echo threshold + if(level >= echo_threshold()) + { + log_message(level, msg, std::cout, false); + } +} + +//----------------------------------------------------------------------------- +void +Logger::log_message(int level, + const std::string &msg, + std::ostream &os, + bool detailed) { /* {parent_indent}- {parent_indent}{indent}level: ... msg txt */ - stream() << m_indent_string <<"-\n"; - stream() << m_indent_string << " level: " << level_string(level) << "\n"; - log_message_inner(msg); + os << m_indent_string <<"-\n"; + os << m_indent_string << " level: " << level_string(level) << "\n"; + if(detailed) + { + os << m_indent_string << " timestamp: \"" << timestamp() << "\"\n"; + } + log_message_inner(msg, os); } //----------------------------------------------------------------------------- void -Logger::log_message_inner(const std::string &msg) +Logger::log_message_inner(const std::string &msg, + std::ostream &os) { /* {parent_indent}{indent}msg: | @@ -179,12 +260,12 @@ Logger::log_message_inner(const std::string &msg) ... {parent_indent}{indent}{indent} msg line */ - stream() << m_indent_string << " msg: |\n"; + os << m_indent_string << " msg: |\n"; std::istringstream input; input.str(msg); for (std::string line; std::getline(input, line);) { - stream() << m_indent_string << " " << line << "\n"; + os << m_indent_string << " " << line << "\n"; } } @@ -212,28 +293,35 @@ Logger::rank() const //----------------------------------------------------------------------------- void -Logger::set_level_threshold(int level) +Logger::set_rank(int rank) +{ + m_rank = rank; +} + +//----------------------------------------------------------------------------- +void +Logger::set_log_threshold(int level) { m_level_threshold = level; } //----------------------------------------------------------------------------- int -Logger::level_threshold() const +Logger::log_threshold() const { return m_level_threshold; } //----------------------------------------------------------------------------- void -Logger::set_echo_level_threshold(int level) +Logger::set_echo_threshold(int level) { m_echo_level_threshold = level; } //----------------------------------------------------------------------------- int -Logger::echo_level_threshold() const +Logger::echo_threshold() const { return m_echo_level_threshold; } @@ -247,17 +335,23 @@ Logger::stream() //----------------------------------------------------------------------------- Logger * -Logger::active_instance() +Logger::instance() { - return m_active_logger; + return m_active_instance; } //----------------------------------------------------------------------------- -Logger * -Logger::activate_instance(const std::string &ofile_pattern) +void +Logger::activate() { - m_active_logger = &m_loggers[ofile_pattern]; - return m_active_logger; + m_active_instance = &m_instance; +} + +//----------------------------------------------------------------------------- +void +Logger::deactivate() +{ + m_active_instance = nullptr; } //----------------------------------------------------------------------------- @@ -275,7 +369,16 @@ Logger::level_string(int level) return m_level_strings[level]; } - +//----------------------------------------------------------------------------- +std::string +Logger::timestamp() +{ + std::time_t time = std::time(nullptr); + auto tm = *std::localtime(&time); + std::ostringstream oss; + oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S"); + return oss.str(); +} //----------------------------------------------------------------------------- }; diff --git a/src/libs/logging/ascent_logging.hpp b/src/libs/logging/ascent_logging.hpp index f1d55dc87..b3f61f3de 100644 --- a/src/libs/logging/ascent_logging.hpp +++ b/src/libs/logging/ascent_logging.hpp @@ -14,8 +14,10 @@ #include #include +#include #include +#include #include /* @@ -38,28 +40,24 @@ ASCENT_LOG_FLUSH() //----------------------------------------------------------------------------- #define ASCENT_LOG_OPEN( ofname_pattern ) \ { \ - ascent::Logger *lgr = ascent::Logger::activate_instance(ofname_pattern); \ + ascent::Logger::activate(); \ + ascent::Logger *lgr = ascent::Logger::instance(); \ lgr->open(ofname_pattern); \ } //----------------------------------------------------------------------------- #define ASCENT_LOG_OPEN_RANK( ofname_pattern , rank ) \ { \ - ascent::Logger *lgr = ascent::Logger::activate_instance(ofname_pattern); \ + ascent::Logger::activate(); \ + ascent::Logger *lgr = ascent::Logger::instance(); \ lgr->set_rank(rank); \ lgr->open(ofname_pattern); \ } -//----------------------------------------------------------------------------- -#define ASCENT_LOG_ACTIVATE( ofname_pattern ) \ -{ \ - Logger::activate_instance(ofname_pattern); \ -} - //----------------------------------------------------------------------------- #define ASCENT_LOG_DEBUG( msg ) \ { \ - ascent::Logger *_ascent_lgr = Logger::active_instance(); \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ if(_ascent_lgr != nullptr) \ { \ std::ostringstream _ascent_oss_info; \ @@ -74,7 +72,7 @@ ASCENT_LOG_FLUSH() //----------------------------------------------------------------------------- #define ASCENT_LOG_INFO( msg ) \ { \ - ascent::Logger *_ascent_lgr = Logger::active_instance(); \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ if(_ascent_lgr != nullptr) \ { \ std::ostringstream _ascent_oss_info; \ @@ -89,7 +87,7 @@ ASCENT_LOG_FLUSH() //----------------------------------------------------------------------------- #define ASCENT_LOG_WARN( msg ) \ { \ - ascent::Logger *_ascent_lgr = Logger::active_instance(); \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ if(_ascent_lgr != nullptr) \ { \ std::ostringstream _ascent_oss_info; \ @@ -104,7 +102,7 @@ ASCENT_LOG_FLUSH() //----------------------------------------------------------------------------- #define ASCENT_LOG_ERROR( msg ) \ { \ - ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ if(_ascent_lgr != nullptr) \ { \ std::ostringstream _ascent_oss_info; \ @@ -117,9 +115,9 @@ ASCENT_LOG_FLUSH() }// TODO EXCEPTION! //----------------------------------------------------------------------------- -#define ASCENT_FLUSH () \ +#define ASCENT_LOG_FLUSH() \ { \ - ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ if(_ascent_lgr != nullptr) \ { \ _ascent_lgr->flush(); \ @@ -127,15 +125,26 @@ ASCENT_LOG_FLUSH() } //----------------------------------------------------------------------------- -#define ASCENT_MARK_SCOPE( name ) ASCENT_ANNOTATE_MARK_SCOPE; ascent::Logger::Scope _ascent_lgr_scope(ascent::Logger::active_instance(), name ); +#define ASCENT_LOG_CLOSE() \ +{ \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ + if(_ascent_lgr != nullptr) \ + { \ + _ascent_lgr->close(); \ + ascent::Logger::deactivate(); \ + } \ +} + +//----------------------------------------------------------------------------- +#define ASCENT_MARK_SCOPE( name ) ASCENT_ANNOTATE_MARK_SCOPE; ascent::Logger::Scope _ascent_lgr_scope(ascent::Logger::instance(), name ); //----------------------------------------------------------------------------- -#define ASCENT_MARK_FUNCTION( name ) ASCENT_ANNOTATE_MARK_FUNCTION; ascent::Logger::Scope _ascent_lgr_func(ascent::Logger::active_instance(), std::string(__func__)); +#define ASCENT_MARK_FUNCTION( name ) ASCENT_ANNOTATE_MARK_FUNCTION; ascent::Logger::Scope _ascent_lgr_func(ascent::Logger::instance(), std::string(__func__)); //----------------------------------------------------------------------------- #define ASCENT_MARK_BEGIN( name ) ASCENT_ANNOTATE_MARK_BEGIN( name ); \ { \ - ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ if(_ascent_lgr != nullptr) \ { \ _ascent_lgr->log_block_begin(name); \ @@ -145,7 +154,7 @@ ASCENT_LOG_FLUSH() //----------------------------------------------------------------------------- #define ASCENT_MARK_END( name ) ASCENT_ANNOTATE_MARK_END( name ); \ { \ - ascent::Logger *_ascent_lgr = ascent::Logger::active_instance(); \ + ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ if(_ascent_lgr != nullptr) \ { \ _ascent_lgr->log_block_end(name); \ @@ -186,10 +195,6 @@ class ASCENT_API Logger std::string m_name; }; - //------------------------------------------------------------------------- - Logger(); - ~Logger(); - // // "ascent_log_out.yaml" // "ascent_log_out_{rank}.yaml" @@ -197,7 +202,7 @@ class ASCENT_API Logger // void open(const std::string &ofile_pattern); - + bool is_open(); void close(); void flush(); @@ -208,6 +213,7 @@ class ASCENT_API Logger void log_message(int level, const std::string &msg); + void log_block_begin(const std::string &name); void log_block_end(const std::string &name); @@ -217,37 +223,67 @@ class ASCENT_API Logger int indent_level() const; void set_indent_level(int level); - // any msgs >= level_threshold will be logged - void set_level_threshold(int level); - int level_threshold() const; - - // any msgs >= echo_level_threshold will sent to std out as well as log - void set_echo_level_threshold(int level); - int echo_level_threshold() const; + // any msgs >= log_threshold will be logged + void set_log_threshold(int level); + int log_threshold() const; + // any msgs >= echo_threshold will sent to std out as well as log + void set_echo_threshold(int level); + int echo_threshold() const; std::ostream &stream(); - static Logger *active_instance(); - static Logger *activate_instance(const std::string &ofile_pattern); + static Logger *instance(); + static void activate(); + static void deactivate(); private: + //------------------------------------------------------------------------- + Logger(); + ~Logger(); + static const std::string &level_string(int level); + std::string timestamp(); - void log_message_inner(const std::string &msg); + void log_message(int level, + const std::string &msg, + const std::string &file, + int line, + std::ostream &os, + bool detailed); + + void log_message(int level, + const std::string &msg, + std::ostream &os, + bool detailed); + + void log_message_inner(const std::string &msg, + std::ostream &os); + + void log_block_begin(const std::string &name, + std::ostream &os); + + void log_block_end(const std::string &name, + std::ostream &os); std::ofstream m_ofstream; - int m_indent_level; // default = 0 + int m_indent_level; // default = 0 int m_indent_spaces; // default = 4 int m_rank; // default = -1 int m_level_threshold; // default = INFO int m_echo_level_threshold; // default = LEGENDARY std::string m_indent_string; // current indent string - - static Logger *m_active_logger; // default = nullptr - static std::map m_loggers; + + // stack of timers + std::stack m_timers; + // stack of block name counters + // used to make sure we have unique keys in our yaml output + std::stack> m_key_counters; + + static Logger m_instance; + static Logger *m_active_instance; // default = nullptr static std::vector m_level_strings; }; diff --git a/src/libs/logging/ascent_logging_timer.cpp b/src/libs/logging/ascent_logging_timer.cpp new file mode 100644 index 000000000..e67959249 --- /dev/null +++ b/src/libs/logging/ascent_logging_timer.cpp @@ -0,0 +1,61 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + + +//----------------------------------------------------------------------------- +/// +/// file: ascent_logging_timer.cpp +/// +//----------------------------------------------------------------------------- + +#include "ascent_logging_timer.hpp" + + +using namespace std::chrono; + +//----------------------------------------------------------------------------- +// -- begin ascent:: -- +//----------------------------------------------------------------------------- +namespace ascent +{ + + +//----------------------------------------------------------------------------- +Timer::Timer() +{ + reset(); +} + +//----------------------------------------------------------------------------- +Timer::~Timer() +{ + +} + +//----------------------------------------------------------------------------- +void +Timer::reset() +{ + m_start = high_resolution_clock::now(); +} + +//----------------------------------------------------------------------------- +float +Timer::elapsed() const +{ + return duration_cast>(high_resolution_clock::now() - m_start).count(); +} + + + +//----------------------------------------------------------------------------- +}; +//----------------------------------------------------------------------------- +// -- end ascent:: -- +//----------------------------------------------------------------------------- + + + diff --git a/src/libs/logging/ascent_logging_timer.hpp b/src/libs/logging/ascent_logging_timer.hpp new file mode 100644 index 000000000..b0e348371 --- /dev/null +++ b/src/libs/logging/ascent_logging_timer.hpp @@ -0,0 +1,56 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + + +//----------------------------------------------------------------------------- +/// +/// file: ascent_logging_timer.hpp +/// +//----------------------------------------------------------------------------- + +#ifndef ASCENT_LOGGING_TIMER_HPP +#define ASCENT_LOGGING_TIMER_HPP + +#include +#include + +//----------------------------------------------------------------------------- +// -- begin ascent:: -- +//----------------------------------------------------------------------------- +namespace ascent +{ + + +//----------------------------------------------------------------------------- +class ASCENT_API Timer +{ + +public: + + explicit Timer(); + ~Timer(); + void reset(); + float elapsed() const; + +private: + std::chrono::high_resolution_clock::time_point m_start; +}; + + +//----------------------------------------------------------------------------- +}; +//----------------------------------------------------------------------------- +// -- end ascent:: -- +//----------------------------------------------------------------------------- + + + +#endif +//----------------------------------------------------------------------------- +// -- end header ifdef guard +//----------------------------------------------------------------------------- + + diff --git a/src/tests/logging/t_ascent_logger_basic.cpp b/src/tests/logging/t_ascent_logger_basic.cpp index 85791e01f..c4207ce4a 100644 --- a/src/tests/logging/t_ascent_logger_basic.cpp +++ b/src/tests/logging/t_ascent_logger_basic.cpp @@ -23,6 +23,30 @@ using namespace std; using namespace conduit; using namespace ascent; + +//----------------------------------------------------------------------------- +void my_func_nest_2() +{ + ASCENT_MARK_FUNCTION(); + ASCENT_LOG_INFO("nest 2"); +} + +//----------------------------------------------------------------------------- +void my_func_nest_1() +{ + ASCENT_MARK_FUNCTION(); + ASCENT_LOG_INFO("nest 1"); + my_func_nest_2(); +} + +//----------------------------------------------------------------------------- +void my_func_nest_0() +{ + ASCENT_MARK_FUNCTION(); + ASCENT_LOG_INFO("nest 0"); + my_func_nest_1(); +} + //----------------------------------------------------------------------------- void myfunc() { @@ -31,9 +55,10 @@ void myfunc() } //----------------------------------------------------------------------------- -TEST(ascent_smoke, ascent_about) +TEST(ascent_logging, basic_logging) { - ASCENT_LOG_OPEN("here_we_go.yaml") + + ASCENT_LOG_OPEN("tout_logging_log_1.yaml"); ASCENT_LOG_INFO("my info!"); ASCENT_LOG_WARN("my warning!"); ASCENT_LOG_ERROR("my error!"); @@ -44,8 +69,57 @@ TEST(ascent_smoke, ascent_about) ASCENT_MARK_END("blocky"); myfunc(); - ASCENT_MARK_BEGIN("blocky2"); + ASCENT_MARK_BEGIN("blocky"); myfunc(); - ASCENT_MARK_END("blocky2"); + ASCENT_MARK_END("blocky"); + + ASCENT_MARK_BEGIN("blocky"); + my_func_nest_0(); + ASCENT_MARK_END("blocky"); + ASCENT_LOG_CLOSE(); + + conduit::Node n; + n.load("tout_logging_log_1.yaml"); + n.print(); + } +//----------------------------------------------------------------------------- +TEST(ascent_logging, basic_logging_echo) +{ + + std::cout << "[echoed]" << std::endl; + ASCENT_LOG_OPEN("tout_logging_log_2.yaml"); + ascent::Logger::instance()->set_echo_threshold(0); + ASCENT_LOG_INFO("my info!"); + ASCENT_LOG_WARN("my warning!"); + ASCENT_LOG_ERROR("my error!"); + ASCENT_LOG_CLOSE(); + + std::cout << "[loaded]" << std::endl; + conduit::Node n; + n.load("tout_logging_log_2.yaml"); + n.print(); + EXPECT_EQ(n.number_of_children(),3); +} + +//----------------------------------------------------------------------------- +TEST(ascent_logging, basic_logging_threshold) +{ + + ASCENT_LOG_OPEN("tout_logging_log_3.yaml"); + ASCENT_LOG_INFO("my info!"); + ascent::Logger::instance()->set_log_threshold(ascent::Logger::LEGENDARY); + ASCENT_LOG_WARN("my warning!"); + ASCENT_LOG_ERROR("my error!"); + ASCENT_LOG_CLOSE(); + + std::cout << "[loaded]" << std::endl; + conduit::Node n; + n.load("tout_logging_log_3.yaml"); + n.print(); + EXPECT_EQ(n.number_of_children(),1); +} + + + From a1207e63f155a2c7c3a278c6d084f58e8f85d99f Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Thu, 21 Nov 2024 16:02:38 -0800 Subject: [PATCH 03/14] gen and use config header --- src/libs/logging/CMakeLists.txt | 8 +++++++- src/libs/logging/ascent_annotations.hpp | 1 + src/libs/logging/ascent_logging.hpp | 1 + src/libs/logging/ascent_logging_config.h.in | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/libs/logging/ascent_logging_config.h.in diff --git a/src/libs/logging/CMakeLists.txt b/src/libs/logging/CMakeLists.txt index 0d93cd9d1..a7af395a3 100644 --- a/src/libs/logging/CMakeLists.txt +++ b/src/libs/logging/CMakeLists.txt @@ -2,7 +2,12 @@ # Project developers. See top-level LICENSE AND COPYRIGHT files for dates and # other details. No copyright assignment is required to contribute to Ascent. +# gen config header +configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/ascent_logging_config.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/ascent_logging_config.h") + set(ascent_logging_headers + ${CMAKE_CURRENT_BINARY_DIR}/ascent_logging_config.h ascent_logging.hpp ascent_logging_timer.hpp ascent_annotations.hpp @@ -27,10 +32,11 @@ blt_add_library(NAME ascent_logging HEADERS ${aascent_logging_headers} DEPENDS_ON ${ascent_logging_deps}) +# for generated config header +target_include_directories(ascent_logging PUBLIC $) target_include_directories(ascent_logging PUBLIC $) # extra defs and props -target_compile_definitions(ascent_logging PUBLIC ASCENT_LOGGING_ENABLE_CALIPER) target_compile_definitions(ascent_logging PRIVATE ASCENT_EXPORTS_FLAG) if(ENABLE_HIDDEN_VISIBILITY) diff --git a/src/libs/logging/ascent_annotations.hpp b/src/libs/logging/ascent_annotations.hpp index 69dcd4743..cac2aa886 100644 --- a/src/libs/logging/ascent_annotations.hpp +++ b/src/libs/logging/ascent_annotations.hpp @@ -15,6 +15,7 @@ // -- ascent includes -- //----------------------------------------------------------------------------- #include +#include #include //----------------------------------------------------------------------------- diff --git a/src/libs/logging/ascent_logging.hpp b/src/libs/logging/ascent_logging.hpp index b3f61f3de..f4a4c1de8 100644 --- a/src/libs/logging/ascent_logging.hpp +++ b/src/libs/logging/ascent_logging.hpp @@ -13,6 +13,7 @@ #define ASCENT_LOGGING_HPP #include +#include #include #include diff --git a/src/libs/logging/ascent_logging_config.h.in b/src/libs/logging/ascent_logging_config.h.in new file mode 100644 index 000000000..b62710f74 --- /dev/null +++ b/src/libs/logging/ascent_logging_config.h.in @@ -0,0 +1,19 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + + +//----------------------------------------------------------------------------- +/// +/// file: ascent_logging_config.h +/// +//----------------------------------------------------------------------------- + +#ifndef ASCENT_LOGGING_CONFIG_H +#define ASCENT_LOGGING_CONFIG_H + +#cmakedefine ASCENT_LOGGING_CALIPER_ENABLED "@CALIPER_FOUND@" + +#endif From 70bd652c13dcc553e49f8f5a169d10a191e4baf8 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Fri, 22 Nov 2024 08:09:31 -0800 Subject: [PATCH 04/14] gen config fix --- src/libs/logging/CMakeLists.txt | 2 ++ src/libs/logging/ascent_logging_config.h.in | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/logging/CMakeLists.txt b/src/libs/logging/CMakeLists.txt index a7af395a3..f68951e28 100644 --- a/src/libs/logging/CMakeLists.txt +++ b/src/libs/logging/CMakeLists.txt @@ -2,7 +2,9 @@ # Project developers. See top-level LICENSE AND COPYRIGHT files for dates and # other details. No copyright assignment is required to contribute to Ascent. + # gen config header +set(ASCENT_LOGGING_ENABLE_CALIPER ${CALIPER_FOUND}) configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/ascent_logging_config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/ascent_logging_config.h") diff --git a/src/libs/logging/ascent_logging_config.h.in b/src/libs/logging/ascent_logging_config.h.in index b62710f74..bb5a9264d 100644 --- a/src/libs/logging/ascent_logging_config.h.in +++ b/src/libs/logging/ascent_logging_config.h.in @@ -14,6 +14,6 @@ #ifndef ASCENT_LOGGING_CONFIG_H #define ASCENT_LOGGING_CONFIG_H -#cmakedefine ASCENT_LOGGING_CALIPER_ENABLED "@CALIPER_FOUND@" +#cmakedefine ASCENT_LOGGING_ENABLE_CALIPER "@CALIPER_FOUND@" #endif From 4a6b6190396097f994cbae8b378fb589beef3886 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Fri, 22 Nov 2024 10:18:14 -0800 Subject: [PATCH 05/14] simplify, more error checking and more tests --- src/libs/logging/ascent_logging.cpp | 188 +++++++++------- src/libs/logging/ascent_logging.hpp | 234 +++++++++----------- src/tests/logging/t_ascent_logger_basic.cpp | 139 ++++++++++-- 3 files changed, 343 insertions(+), 218 deletions(-) diff --git a/src/libs/logging/ascent_logging.cpp b/src/libs/logging/ascent_logging.cpp index d16cf1613..ac4f2d82c 100644 --- a/src/libs/logging/ascent_logging.cpp +++ b/src/libs/logging/ascent_logging.cpp @@ -31,41 +31,32 @@ using namespace conduit; namespace ascent { +//----------------------------------------------------------------------------- +// main logger instance +//----------------------------------------------------------------------------- Logger Logger::m_instance; -Logger *Logger::m_active_instance = nullptr; -std::vector Logger::m_level_strings = {"unset", - "debug", - "info", - "warn", - "error", - "legendary"}; //----------------------------------------------------------------------------- -Logger::Scope::Scope(Logger *lgr, const std::string &name) +Logger::Scope::Scope(Logger &lgr, const std::string &name) : m_lgr(lgr), m_name(name) { - if(m_lgr != nullptr) - { - m_lgr->log_block_begin(m_name); - } + m_lgr.log_block_begin(m_name); } //----------------------------------------------------------------------------- Logger::Scope::~Scope() { - if(m_lgr != nullptr) - { - m_lgr->log_block_end(m_name); - } + m_lgr.log_block_end(m_name); } //----------------------------------------------------------------------------- Logger::Logger() - : m_indent_level(0), + : m_log_open(false), + m_indent_level(0), m_rank(-1), - m_level_threshold(INFO), - m_echo_level_threshold(LEGENDARY) + m_log_threshold(Logger::INFO), + m_echo_threshold(Logger::NONE) { m_key_counters.push(std::map()); } @@ -76,72 +67,111 @@ Logger::~Logger() close(); } +//----------------------------------------------------------------------------- +void +Logger::reset() +{ + m_indent_level = 0; + m_log_threshold = Logger::INFO; + m_echo_threshold = Logger::NONE; + // reset our stacks + m_timers = std::stack(); + m_key_counters = std::stack>(); + m_key_counters.push(std::map()); +} + //----------------------------------------------------------------------------- void Logger::open(const std::string &ofpattern) { + if(is_log_open()) + { + std::string emsg = conduit_fmt::format("[FATAL_ERROR] failed to open log with pattern: {}, logger already has {} open.", + ofpattern, m_log_fname); + throw conduit::Error(emsg, + __FILE__, + __LINE__); + } + // multi node case, assumes file pattern includes "rank" - std::string ofname; if(rank() > -1) { - ofname = conduit_fmt::format(ofpattern, - conduit_fmt::arg("rank",rank())); + m_log_fname = conduit_fmt::format(ofpattern, + conduit_fmt::arg("rank",rank())); } else { - ofname = ofpattern; + m_log_fname = ofpattern; } - m_ofstream.open(ofname.c_str()); + // open append (consequtive ascent open use cases) + m_log_stream.open(m_log_fname.c_str(),std::ios_base::app); - if(!m_ofstream.is_open()) + if(!m_log_stream.is_open()) { - std::cerr << "[ERROR] Failed to open log file: " << ofname << std::endl; + throw conduit::Error(conduit_fmt::format("[FATAL_ERROR] Failed to open log file: {} ", m_log_fname), + __FILE__, + __LINE__); } + m_log_open = true; + log_message(Logger::DEBUG,conduit_fmt::format("opened log file: {}", m_log_fname)); } //----------------------------------------------------------------------------- bool -Logger::is_open() +Logger::is_log_open() { - return m_ofstream.is_open(); + return m_log_open; } //----------------------------------------------------------------------------- void Logger::close() { - if(m_ofstream.is_open()) + if(is_log_open()) { - m_ofstream.close(); + log_message(Logger::DEBUG,conduit_fmt::format("closing log file: {}", m_log_fname)); + m_log_stream.close(); + m_log_open = false; + m_log_fname = ""; } + + reset(); } //----------------------------------------------------------------------------- void Logger::flush() { - m_ofstream << std::flush; + if(is_log_open()) + { + log_stream() << std::flush; + } } //----------------------------------------------------------------------------- void Logger::log_block_begin(const std::string &name) { + // skip if log is not open + if(!is_log_open()) + { + return; + } + // make sure we have a unique key name - int key_count = m_key_counters.top()[name]++; - stream() << m_indent_string <<"-\n"; + log_stream() << m_indent_string <<"-\n"; set_indent_level(indent_level()+1); if(key_count == 0) { - stream() << m_indent_string << name << ":\n"; + log_stream() << m_indent_string << name << ":\n"; } else { - stream() << m_indent_string << name << "_" << key_count <<":\n"; + log_stream() << m_indent_string << name << "_" << key_count <<":\n"; } set_indent_level(indent_level()+1); // add timer for new level @@ -154,8 +184,14 @@ Logger::log_block_begin(const std::string &name) void Logger::log_block_end(const std::string &name) { - stream() << m_indent_string <<"-\n"; - stream() << m_indent_string << " time_elapsed: " << m_timers.top().elapsed() << "\n"; + // skip if log is not open + if(!is_log_open()) + { + return; + } + + log_stream() << m_indent_string <<"-\n"; + log_stream() << m_indent_string << " time_elapsed: " << m_timers.top().elapsed() << "\n"; set_indent_level(indent_level()-2); m_key_counters.pop(); m_timers.pop(); @@ -168,17 +204,17 @@ Logger::log_message(int level, const std::string &file, int line) { - // log if equal or above logging threshold - if(level >= log_threshold()) - { - log_message(level, msg, file, line, stream(), true); - } - // echo if equal or above echo threshold if(level >= echo_threshold()) { log_message(level, msg, file, line, std::cout, false); } + + // log if equal or above logging threshold + if(level >= log_threshold()) + { + log_message(level, msg, file, line, log_stream(), true); + } } @@ -214,17 +250,17 @@ void Logger::log_message(int level, const std::string &msg) { - // log if equal or above logging threshold - if(level >= log_threshold()) - { - log_message(level, msg, stream(), true); - } - // echo if equal or above echo threshold if(level >= echo_threshold()) { log_message(level, msg, std::cout, false); } + + // log if equal or above logging threshold + if(level >= log_threshold()) + { + log_message(level, msg, log_stream(), true); + } } //----------------------------------------------------------------------------- @@ -302,71 +338,69 @@ Logger::set_rank(int rank) void Logger::set_log_threshold(int level) { - m_level_threshold = level; + m_log_threshold = level; } //----------------------------------------------------------------------------- int Logger::log_threshold() const { - return m_level_threshold; + return m_log_threshold; } //----------------------------------------------------------------------------- void Logger::set_echo_threshold(int level) { - m_echo_level_threshold = level; + m_echo_threshold = level; } //----------------------------------------------------------------------------- int Logger::echo_threshold() const { - return m_echo_level_threshold; + return m_echo_threshold; } //----------------------------------------------------------------------------- std::ostream & -Logger::stream() +Logger::log_stream() { - return m_ofstream; + return m_log_stream; } //----------------------------------------------------------------------------- -Logger * +Logger & Logger::instance() { - return m_active_instance; -} - -//----------------------------------------------------------------------------- -void -Logger::activate() -{ - m_active_instance = &m_instance; -} - -//----------------------------------------------------------------------------- -void -Logger::deactivate() -{ - m_active_instance = nullptr; + return m_instance; } //----------------------------------------------------------------------------- -const std::string & +std::string Logger::level_string(int level) { - if(level < Logger::UNKNOWN ) + if(level < Logger::ALL ) + { + level = Logger::ALL; + } + else if(level < Logger::DEBUG) + { + level = Logger::DEBUG; + } + else if(level > Logger::ERROR) { - level = Logger::UNKNOWN; + level = Logger::NONE; } - else if(level > Logger::LEGENDARY) + switch(level) { - level = Logger::LEGENDARY; + case Logger::ALL: return "all"; break; + case Logger::DEBUG: return "debug"; break; + case Logger::INFO: return "info"; break; + case Logger::WARN: return "warn"; break; + case Logger::ERROR: return "error"; break; + case Logger::NONE: return "none"; break; } - return m_level_strings[level]; } //----------------------------------------------------------------------------- diff --git a/src/libs/logging/ascent_logging.hpp b/src/libs/logging/ascent_logging.hpp index f4a4c1de8..4ae985427 100644 --- a/src/libs/logging/ascent_logging.hpp +++ b/src/libs/logging/ascent_logging.hpp @@ -21,14 +21,20 @@ #include #include +//----------------------------------------------------------------------------- /* + +Unified Logging Macros used by all libraries.alignas + +macros: + ASCENT_LOG_OPEN( output_file_name_pattern ) // serial ASCENT_LOG_OPEN( output_file_name_pattern, rank ) // mpi par -ASCENT_LOG_DEBUG( msg ) (w/ line, file, etc) -ASCENT_LOG_INFO( msg ) (w/ line, file, etc) -ASCENT_LOG_WARN( msg ) (w/ line, file, etc) -ASCENT_LOG_ERROR( msg ) (w/ line, file, etc) +ASCENT_LOG_DEBUG( msg ) (w/ line, file) +ASCENT_LOG_INFO( msg ) (w/ line, file) +ASCENT_LOG_WARN( msg ) (w/ line, file) +ASCENT_LOG_ERROR( msg ) (w/ line, file) ASCENT_LOG_SCOPE( name ) --> increase indent ASCENT_LOG_MARK_BEGIN( name ) --> increase indent @@ -36,104 +42,82 @@ ASCENT_LOG_MARK_END( name ) --> decrease indent ASCENT_LOG_MARK_FUNCTION () ASCENT_LOG_FLUSH() +ASCENT_LOG_CLOSE() */ +//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -#define ASCENT_LOG_OPEN( ofname_pattern ) \ -{ \ - ascent::Logger::activate(); \ - ascent::Logger *lgr = ascent::Logger::instance(); \ - lgr->open(ofname_pattern); \ +#define ASCENT_LOG_OPEN( ofname_pattern ) \ +{ \ + ascent::Logger::instance().open(ofname_pattern); \ } //----------------------------------------------------------------------------- -#define ASCENT_LOG_OPEN_RANK( ofname_pattern , rank ) \ -{ \ - ascent::Logger::activate(); \ - ascent::Logger *lgr = ascent::Logger::instance(); \ - lgr->set_rank(rank); \ - lgr->open(ofname_pattern); \ +#define ASCENT_LOG_OPEN_RANK( ofname_pattern , rank ) \ +{ \ + ascent::Logger &lgr = ascent::Logger::instance(); \ + lgr.set_rank(rank); \ + lgr.open(ofname_pattern); \ } //----------------------------------------------------------------------------- -#define ASCENT_LOG_DEBUG( msg ) \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - std::ostringstream _ascent_oss_info; \ - _ascent_oss_info << msg; \ - _ascent_lgr->log_message(ascent::Logger::DEBUG, \ - _ascent_oss_info.str(), \ - std::string(__FILE__), \ - __LINE__); \ - } \ +#define ASCENT_LOG_DEBUG( msg ) \ +{ \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + ascent::Logger::instance().log_message(ascent::Logger::DEBUG, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ } //----------------------------------------------------------------------------- -#define ASCENT_LOG_INFO( msg ) \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - std::ostringstream _ascent_oss_info; \ - _ascent_oss_info << msg; \ - _ascent_lgr->log_message(ascent::Logger::INFO, \ - _ascent_oss_info.str(), \ - std::string(__FILE__), \ - __LINE__); \ - } \ +#define ASCENT_LOG_INFO( msg ) \ +{ \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + ascent::Logger::instance().log_message(ascent::Logger::INFO, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ } //----------------------------------------------------------------------------- -#define ASCENT_LOG_WARN( msg ) \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - std::ostringstream _ascent_oss_info; \ - _ascent_oss_info << msg; \ - _ascent_lgr->log_message(ascent::Logger::WARN, \ - _ascent_oss_info.str(), \ - std::string(__FILE__), \ - __LINE__); \ - } \ +#define ASCENT_LOG_WARN( msg ) \ +{ \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + ascent::Logger::instance().log_message(ascent::Logger::WARN, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ } //----------------------------------------------------------------------------- -#define ASCENT_LOG_ERROR( msg ) \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - std::ostringstream _ascent_oss_info; \ - _ascent_oss_info << msg; \ - _ascent_lgr->log_message(ascent::Logger::ERROR, \ - _ascent_oss_info.str(), \ - std::string(__FILE__), \ - __LINE__); \ - } \ -}// TODO EXCEPTION! +#define ASCENT_LOG_ERROR( msg ) \ +{ \ + std::ostringstream _ascent_oss_info; \ + _ascent_oss_info << msg; \ + ascent::Logger::instance().log_message(ascent::Logger::ERROR, \ + _ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ + ascent::Logger::instance().flush(); \ + throw conduit::Error(_ascent_oss_info.str(), \ + std::string(__FILE__), \ + __LINE__); \ +} //----------------------------------------------------------------------------- -#define ASCENT_LOG_FLUSH() \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - _ascent_lgr->flush(); \ - } \ +#define ASCENT_LOG_FLUSH() \ +{ \ + ascent::Logger::instance().flush(); \ } //----------------------------------------------------------------------------- -#define ASCENT_LOG_CLOSE() \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - _ascent_lgr->close(); \ - ascent::Logger::deactivate(); \ - } \ +#define ASCENT_LOG_CLOSE() \ +{ \ + ascent::Logger::instance().close(); \ } //----------------------------------------------------------------------------- @@ -143,26 +127,17 @@ ASCENT_LOG_FLUSH() #define ASCENT_MARK_FUNCTION( name ) ASCENT_ANNOTATE_MARK_FUNCTION; ascent::Logger::Scope _ascent_lgr_func(ascent::Logger::instance(), std::string(__func__)); //----------------------------------------------------------------------------- -#define ASCENT_MARK_BEGIN( name ) ASCENT_ANNOTATE_MARK_BEGIN( name ); \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - _ascent_lgr->log_block_begin(name); \ - } \ +#define ASCENT_MARK_BEGIN( name ) ASCENT_ANNOTATE_MARK_BEGIN( name ); \ +{ \ + ascent::Logger::instance().log_block_begin(name); \ } //----------------------------------------------------------------------------- -#define ASCENT_MARK_END( name ) ASCENT_ANNOTATE_MARK_END( name ); \ -{ \ - ascent::Logger *_ascent_lgr = ascent::Logger::instance(); \ - if(_ascent_lgr != nullptr) \ - { \ - _ascent_lgr->log_block_end(name); \ - } \ +#define ASCENT_MARK_END( name ) ASCENT_ANNOTATE_MARK_END( name ); \ +{ \ + ascent::Logger::instance().log_block_end(name); \ } - //----------------------------------------------------------------------------- // -- begin ascent:: -- //----------------------------------------------------------------------------- @@ -177,33 +152,34 @@ class ASCENT_API Logger //------------------------------------------------------------------------- typedef enum { - UNKNOWN = -1, - DEBUG = 1, - INFO = 2, - WARN = 3, - ERROR = 4, - LEGENDARY = 5, + ALL = -1, // lowest + DEBUG = 1, + INFO = 2, + WARN = 3, + ERROR = 4, + NONE = 127, // highest } MessageLevel; //------------------------------------------------------------------------- class ASCENT_API Scope { public: - Scope(Logger *lgr, const std::string &name); + Scope(Logger &lgr, const std::string &name); ~Scope(); private: - Logger *m_lgr; + Logger &m_lgr; std::string m_name; }; // - // "ascent_log_out.yaml" - // "ascent_log_out_{rank}.yaml" - // "ascent_log_out_{rank:05d}.yaml" + // file pattern examples: + // "ascent_log_out.yaml" + // "ascent_log_out_{rank}.yaml" + // "ascent_log_out_{rank:05d}.yaml" // - void open(const std::string &ofile_pattern); - bool is_open(); + bool is_log_open(); + void reset(); // reset to defaults void close(); void flush(); @@ -232,19 +208,21 @@ class ASCENT_API Logger void set_echo_threshold(int level); int echo_threshold() const; - std::ostream &stream(); - - static Logger *instance(); - static void activate(); - static void deactivate(); + std::ostream &log_stream(); + static Logger &instance(); private: //------------------------------------------------------------------------- + // constructor + destructor + // ------------------------------------------------------------------------ Logger(); ~Logger(); - static const std::string &level_string(int level); - std::string timestamp(); + // ------------------------------------------------------------------------ + // helpers + // ------------------------------------------------------------------------ + static std::string level_string(int level); + static std::string timestamp(); void log_message(int level, const std::string &msg, @@ -267,25 +245,31 @@ class ASCENT_API Logger void log_block_end(const std::string &name, std::ostream &os); - std::ofstream m_ofstream; - - int m_indent_level; // default = 0 - int m_indent_spaces; // default = 4 - int m_rank; // default = -1 - int m_level_threshold; // default = INFO - int m_echo_level_threshold; // default = LEGENDARY - - std::string m_indent_string; // current indent string + // ------------------------------------------------------------------------ + // instance vars + // ------------------------------------------------------------------------ + std::ofstream m_log_stream; + bool m_log_open; + std::string m_log_fname; + int m_indent_level; // default = 0 + int m_rank; // default = -1 + int m_log_threshold; // default = INFO + int m_echo_threshold; // default = NONE + std::string m_indent_string; // current indent string + // ------------------------------------------------------------------------ + // logging state stacks + // ------------------------------------------------------------------------ // stack of timers std::stack m_timers; // stack of block name counters // used to make sure we have unique keys in our yaml output std::stack> m_key_counters; + // ------------------------------------------------------------------------ + // static members + // ------------------------------------------------------------------------ static Logger m_instance; - static Logger *m_active_instance; // default = nullptr - static std::vector m_level_strings; }; //----------------------------------------------------------------------------- diff --git a/src/tests/logging/t_ascent_logger_basic.cpp b/src/tests/logging/t_ascent_logger_basic.cpp index c4207ce4a..352f9e0f7 100644 --- a/src/tests/logging/t_ascent_logger_basic.cpp +++ b/src/tests/logging/t_ascent_logger_basic.cpp @@ -57,15 +57,16 @@ void myfunc() //----------------------------------------------------------------------------- TEST(ascent_logging, basic_logging) { - - ASCENT_LOG_OPEN("tout_logging_log_1.yaml"); + // remove file if it exists + std::string lfname = "tout_logging_log_1.yaml"; + conduit::utils::remove_path_if_exists(lfname); + ASCENT_LOG_OPEN(lfname); + ASCENT_LOG_DEBUG("my debug!"); ASCENT_LOG_INFO("my info!"); ASCENT_LOG_WARN("my warning!"); - ASCENT_LOG_ERROR("my error!"); ASCENT_MARK_BEGIN("blocky"); ASCENT_LOG_INFO("my info!"); ASCENT_LOG_WARN("my warning!"); - ASCENT_LOG_ERROR("my error!"); ASCENT_MARK_END("blocky"); myfunc(); @@ -79,7 +80,7 @@ TEST(ascent_logging, basic_logging) ASCENT_LOG_CLOSE(); conduit::Node n; - n.load("tout_logging_log_1.yaml"); + n.load(lfname); n.print(); } @@ -87,39 +88,145 @@ TEST(ascent_logging, basic_logging) //----------------------------------------------------------------------------- TEST(ascent_logging, basic_logging_echo) { - + // remove file if it exists + std::string lfname = "tout_logging_log_2.yaml"; + conduit::utils::remove_path_if_exists(lfname); + ascent::Logger::instance().set_echo_threshold(ascent::Logger::ALL); std::cout << "[echoed]" << std::endl; - ASCENT_LOG_OPEN("tout_logging_log_2.yaml"); - ascent::Logger::instance()->set_echo_threshold(0); + ASCENT_LOG_OPEN(lfname); + ASCENT_LOG_DEBUG("my debug!"); ASCENT_LOG_INFO("my info!"); ASCENT_LOG_WARN("my warning!"); - ASCENT_LOG_ERROR("my error!"); ASCENT_LOG_CLOSE(); std::cout << "[loaded]" << std::endl; conduit::Node n; - n.load("tout_logging_log_2.yaml"); + n.load(lfname); n.print(); - EXPECT_EQ(n.number_of_children(),3); + // we should have 2 msgs above debug + EXPECT_EQ(n.number_of_children(),2); } //----------------------------------------------------------------------------- TEST(ascent_logging, basic_logging_threshold) { - - ASCENT_LOG_OPEN("tout_logging_log_3.yaml"); + // remove file if it exists + std::string lfname = "tout_logging_log_3.yaml"; + conduit::utils::remove_path_if_exists(lfname); + ASCENT_LOG_OPEN(lfname); ASCENT_LOG_INFO("my info!"); - ascent::Logger::instance()->set_log_threshold(ascent::Logger::LEGENDARY); + ascent::Logger::instance().set_log_threshold(ascent::Logger::NONE); ASCENT_LOG_WARN("my warning!"); - ASCENT_LOG_ERROR("my error!"); ASCENT_LOG_CLOSE(); std::cout << "[loaded]" << std::endl; conduit::Node n; - n.load("tout_logging_log_3.yaml"); + n.load(lfname); + n.print(); + // we should have 1 msg above debug + EXPECT_EQ(n.number_of_children(),1); +} + +//----------------------------------------------------------------------------- +TEST(ascent_logging, basic_logging_error) +{ + bool error_occured = false; + try + { + ASCENT_LOG_ERROR("my error!"); + } + catch (conduit::Error &error) + { + std::cout << error.what() << std::endl; + error_occured = true; + } + EXPECT_TRUE(error_occured); + + // now check error inside log file + // remove file if it exists + std::string lfname = "tout_logging_log_4.yaml"; + conduit::utils::remove_path_if_exists(lfname); + ASCENT_LOG_OPEN(lfname); + + error_occured = false; + try + { + ASCENT_LOG_ERROR("my error!"); + } + catch (conduit::Error &error) + { + std::cout << error.what() << std::endl; + error_occured = true; + } + EXPECT_TRUE(error_occured); + + ASCENT_LOG_CLOSE(); + std::cout << "[loaded]" << std::endl; + conduit::Node n; + n.load(lfname); n.print(); + // we should have 1 msg above debug EXPECT_EQ(n.number_of_children(),1); } +//----------------------------------------------------------------------------- +TEST(ascent_logging, basic_logging_append) +{ + // remove file if it exists + std::string lfname = "tout_logging_log_5.yaml"; + conduit::utils::remove_path_if_exists(lfname); + ascent::Logger::instance().set_log_threshold(ascent::Logger::ALL); + ASCENT_LOG_OPEN(lfname); + ASCENT_LOG_INFO("my debug 1!"); + ASCENT_LOG_INFO("my info 1!"); + ASCENT_LOG_WARN("my warning 1!"); + ASCENT_LOG_CLOSE(); + ascent::Logger::instance().set_log_threshold(ascent::Logger::ALL); + ASCENT_LOG_OPEN(lfname); + ASCENT_LOG_INFO("my debug 2!"); + ASCENT_LOG_INFO("my info 2!"); + ASCENT_LOG_WARN("my warning 2!"); + ASCENT_LOG_CLOSE(); + std::cout << "[loaded]" << std::endl; + conduit::Node n; + n.load(lfname); + n.print(); + // we should have 5 * 2 (open, close, + 1 debug, + 1 info, + 1 warn) + EXPECT_EQ(n.number_of_children(),10); +} + + +//----------------------------------------------------------------------------- +TEST(ascent_logging, basic_logging_error_bad_log_file) +{ + bool error_occured = false; + try + { + ASCENT_LOG_OPEN("/blargh/totally/bogus/des/path/to/log/file.yaml"); + } + catch (conduit::Error &error) + { + std::cout << error.what() << std::endl; + error_occured = true; + } + EXPECT_TRUE(error_occured); + + // remove file if it exists + std::string lfname = "tout_logging_log_6.yaml"; + conduit::utils::remove_path_if_exists(lfname); + error_occured =false; + try + { + // double open should throw an exception + ASCENT_LOG_OPEN(lfname); + ASCENT_LOG_OPEN(lfname); + } + catch (conduit::Error &error) + { + std::cout << error.what() << std::endl; + error_occured = true; + } + EXPECT_TRUE(error_occured); +} From f11cdd35ee30f67f014304bd357752e1e1860551 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Fri, 22 Nov 2024 10:20:20 -0800 Subject: [PATCH 06/14] add close to test --- src/tests/logging/t_ascent_logger_basic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/logging/t_ascent_logger_basic.cpp b/src/tests/logging/t_ascent_logger_basic.cpp index 352f9e0f7..e6eaa02d6 100644 --- a/src/tests/logging/t_ascent_logger_basic.cpp +++ b/src/tests/logging/t_ascent_logger_basic.cpp @@ -229,4 +229,5 @@ TEST(ascent_logging, basic_logging_error_bad_log_file) error_occured = true; } EXPECT_TRUE(error_occured); + ASCENT_LOG_CLOSE(); } From 37b805f5979df7449700d909649a8393c81d382b Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 9 Dec 2024 09:54:32 -0800 Subject: [PATCH 07/14] wire init of new logging, keep old marcos wired --- src/libs/ascent/CMakeLists.txt | 4 +- src/libs/ascent/ascent.cpp | 151 +++++++++++++++++- src/libs/ascent/ascent.hpp | 1 + src/libs/ascent/hola/ascent_hola.cpp | 1 + .../ascent/runtimes/ascent_main_runtime.cpp | 9 ++ .../runtimes/ascent_mfem_data_adapter.cpp | 1 + .../ascent/runtimes/ascent_transmogrifier.cpp | 1 + .../runtimes/ascent_vtkh_collection.cpp | 1 + .../runtimes/ascent_vtkh_data_adapter.cpp | 3 + .../expressions/ascent_array_internals.hpp | 1 + .../ascent_blueprint_type_utils.hpp | 1 + .../expressions/ascent_execution_manager.cpp | 1 + .../runtimes/expressions/ascent_jit_array.cpp | 1 + .../runtimes/expressions/ascent_jit_field.cpp | 1 + .../runtimes/expressions/ascent_jit_math.cpp | 1 + .../expressions/ascent_memory_manager.cpp | 1 + ...ascent_runtime_conduit_to_vtkm_parsing.cpp | 2 + ...ent_logging.cpp => ascent_logging_old.cpp} | 4 +- ...ent_logging.hpp => ascent_logging_old.hpp} | 4 +- src/libs/logging/ascent_logging.cpp | 57 ++++++- src/libs/logging/ascent_logging.hpp | 5 +- 21 files changed, 233 insertions(+), 18 deletions(-) rename src/libs/ascent/utils/{ascent_logging.cpp => ascent_logging_old.cpp} (94%) rename src/libs/ascent/utils/{ascent_logging.hpp => ascent_logging_old.hpp} (98%) diff --git a/src/libs/ascent/CMakeLists.txt b/src/libs/ascent/CMakeLists.txt index 730dd6744..c170c6dfd 100644 --- a/src/libs/ascent/CMakeLists.txt +++ b/src/libs/ascent/CMakeLists.txt @@ -171,7 +171,7 @@ set(ascent_headers # utils utils/ascent_actions_utils.hpp utils/ascent_data_logger.hpp - utils/ascent_logging.hpp + utils/ascent_logging_old.hpp utils/ascent_block_timer.hpp utils/ascent_mpi_utils.hpp utils/ascent_string_utils.hpp @@ -237,7 +237,7 @@ set(ascent_sources utils/ascent_actions_utils.cpp utils/ascent_data_logger.cpp utils/ascent_block_timer.cpp - utils/ascent_logging.cpp + utils/ascent_logging_old.cpp utils/ascent_mpi_utils.cpp utils/ascent_string_utils.cpp utils/ascent_web_interface.cpp diff --git a/src/libs/ascent/ascent.cpp b/src/libs/ascent/ascent.cpp index 0b80db005..c23fd0703 100644 --- a/src/libs/ascent/ascent.cpp +++ b/src/libs/ascent/ascent.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include #include @@ -36,6 +38,38 @@ using namespace conduit; namespace ascent { +//----------------------------------------------------------------------------- +namespace detail +{ + +//----------------------------------------------------------------------------- +int +ParRank(int comm_id) +{ + int rank = 0; + +#if defined(ASCENT_MPI_ENABLED) + MPI_Comm mpi_comm = MPI_Comm_f2c(comm_id); + MPI_Comm_rank(mpi_comm, &rank); +#endif + + return rank; +} + +//----------------------------------------------------------------------------- +int +ParSize(int comm_id) +{ +int comm_size=1; + +#if defined(ASCENT_MPI_ENABLED) + MPI_Comm mpi_comm = MPI_Comm_f2c(comm_id); + MPI_Comm_size(mpi_comm, &comm_size); +#endif + + return comm_size; +} + //----------------------------------------------------------------------------- void quiet_handler(const std::string &, @@ -44,6 +78,10 @@ quiet_handler(const std::string &, { } +} + + + //----------------------------------------------------------------------------- Ascent::Ascent() : m_runtime(NULL), @@ -187,6 +225,9 @@ Ascent::open(const conduit::Node &options) comm_id = options["mpi_comm"].to_int32(); } + int par_rank = detail::ParRank(comm_id); + int par_size = detail::ParSize(comm_id); + CheckForSettingsFile(opts_file, processed_opts, true, @@ -201,20 +242,114 @@ Ascent::open(const conduit::Node &options) m_options["mpi_comm"] = options["mpi_comm"]; } - if(m_options.has_path("messages") && - m_options["messages"].dtype().is_string() ) + Node echo_opts; + echo_opts["echo_threshold"] = "info"; + echo_opts["ranks"] = "root"; + + // messages echoed to std out + if(m_options.has_path("messages")) + { + if(m_options["messages"].dtype().is_string()) + { + std::string msgs_opt = m_options["messages"].as_string(); + if( msgs_opt == "verbose") + { + m_verbose_msgs = true; + echo_opts["echo_threshold"] = "all"; + } + else if(msgs_opt == "quiet") + { + m_verbose_msgs = false; + echo_opts["echo_threshold"] = "error"; + } + } + else if(m_options["messages"].dtype().is_object()) + { + const Node &msg_ops = m_options["messages"]; + echo_opts.update(msg_ops); + if(msg_ops.has_child("echo_threshold") && + msg_ops["echo_threshold"].dtype().is_string() ) + { + std::string echo_thresh = msg_ops["echo_threshold"].as_string(); + if(echo_thresh == "none" || + echo_thresh == "error" || + echo_thresh == "warn" ) + { + m_verbose_msgs = false; + } + else + { + m_verbose_msgs = true; + } + } + } + } + + ascent::Logger &logger = ascent::Logger::instance(); + + // setup echo + logger.set_echo_threshold(echo_opts["echo_threshold"].as_string()); + + // control for mpi case + // if ranks == "root" + // rank 0 is what is specified, echo_threshold = "none" for all others + // if ranks == "all" + // echo_threshold = specified option used for all ranks (alreay handled above) + std::string log_ranks_str = echo_opts["ranks"].as_string(); + + if(log_ranks_str == "root") + { + if(par_rank != 0) + { + logger.set_echo_threshold(ascent::Logger::NONE); + } + } + + // logging options + // + // logging: true + // + // logging: + // file_pattern: zzzz + // log_threshold: info + // + + Node logging_opts; + logging_opts["enabled"] = 0; +#if defined(ASCENT_MPI_ENABLED) + logging_opts["file_pattern"] = "ascent_log_output.yaml"; +#else + logging_opts["file_pattern"] = "ascent_log_output_rank{rank:05d}.yaml"; +#endif + logging_opts["log_threshold"] = "info"; + + if(m_options.has_path("logging")) { - std::string msgs_opt = m_options["messages"].as_string(); - if( msgs_opt == "verbose") + if(m_options["logging"].dtype().is_string() && + m_options["logging"].as_string() == "true") { - m_verbose_msgs = true; + logging_opts["enabled"] = 1; } - else if(msgs_opt == "quiet") + else if(m_options["logging"].dtype().is_object()) { - m_verbose_msgs = false; + logging_opts["enabled"] = 1; + // pull over options + logging_opts.update(m_options["logging"]); } } + if(logging_opts["enabled"].to_int() == 1) + { + std::string file_pattern = logging_opts["file_pattern"].as_string(); + #if defined(ASCENT_MPI_ENABLED) + ASCENT_LOG_OPEN( file_pattern ) // serial + #else + ASCENT_LOG_OPEN_RANK( file_pattern, par_rank ) // mpi par + #endif + } + + + // exception controls if(m_options.has_path("exceptions") && m_options["exceptions"].dtype().is_string() ) { @@ -300,7 +435,7 @@ Ascent::open(const conduit::Node &options) // make sure to do this after. if(!m_verbose_msgs) { - conduit::utils::set_info_handler(quiet_handler); + conduit::utils::set_info_handler(detail::quiet_handler); } set_status("Ascent::open completed"); diff --git a/src/libs/ascent/ascent.hpp b/src/libs/ascent/ascent.hpp index 765f70651..44757aa17 100644 --- a/src/libs/ascent/ascent.hpp +++ b/src/libs/ascent/ascent.hpp @@ -20,6 +20,7 @@ #include +#include #include #include diff --git a/src/libs/ascent/hola/ascent_hola.cpp b/src/libs/ascent/hola/ascent_hola.cpp index a61d0409b..4934bc1f4 100644 --- a/src/libs/ascent/hola/ascent_hola.cpp +++ b/src/libs/ascent/hola/ascent_hola.cpp @@ -25,6 +25,7 @@ // ascent includes //----------------------------------------------------------------------------- #include +#include #include diff --git a/src/libs/ascent/runtimes/ascent_main_runtime.cpp b/src/libs/ascent/runtimes/ascent_main_runtime.cpp index 0b8332d27..83c1dabc0 100644 --- a/src/libs/ascent/runtimes/ascent_main_runtime.cpp +++ b/src/libs/ascent/runtimes/ascent_main_runtime.cpp @@ -131,6 +131,15 @@ AscentRuntime::~AscentRuntime() void AscentRuntime::Initialize(const conduit::Node &options) { + +// handle logging first +#if defined(ASCENT_MPI_ENABLED) + +#else + +#endif + + #if ASCENT_MPI_ENABLED if(!options.has_child("mpi_comm") || !options["mpi_comm"].dtype().is_integer()) diff --git a/src/libs/ascent/runtimes/ascent_mfem_data_adapter.cpp b/src/libs/ascent/runtimes/ascent_mfem_data_adapter.cpp index 08ae7988a..fec8e11c5 100644 --- a/src/libs/ascent/runtimes/ascent_mfem_data_adapter.cpp +++ b/src/libs/ascent/runtimes/ascent_mfem_data_adapter.cpp @@ -13,6 +13,7 @@ #include "ascent_mfem_data_adapter.hpp" #include +#include // standard lib includes #include diff --git a/src/libs/ascent/runtimes/ascent_transmogrifier.cpp b/src/libs/ascent/runtimes/ascent_transmogrifier.cpp index a9cfc8573..535f05c76 100644 --- a/src/libs/ascent/runtimes/ascent_transmogrifier.cpp +++ b/src/libs/ascent/runtimes/ascent_transmogrifier.cpp @@ -17,6 +17,7 @@ #include "ascent_mfem_data_adapter.hpp" #endif #include "ascent_logging.hpp" +#include "ascent_logging_old.hpp" #include #include diff --git a/src/libs/ascent/runtimes/ascent_vtkh_collection.cpp b/src/libs/ascent/runtimes/ascent_vtkh_collection.cpp index d73abe3af..d24cbac37 100644 --- a/src/libs/ascent/runtimes/ascent_vtkh_collection.cpp +++ b/src/libs/ascent/runtimes/ascent_vtkh_collection.cpp @@ -14,6 +14,7 @@ #include "ascent_vtkh_collection.hpp" #include "ascent_mpi_utils.hpp" #include "ascent_logging.hpp" +#include "ascent_logging_old.hpp" #if defined(ASCENT_MPI_ENABLED) #include diff --git a/src/libs/ascent/runtimes/ascent_vtkh_data_adapter.cpp b/src/libs/ascent/runtimes/ascent_vtkh_data_adapter.cpp index 82caa2ca2..2dae0b825 100644 --- a/src/libs/ascent/runtimes/ascent_vtkh_data_adapter.cpp +++ b/src/libs/ascent/runtimes/ascent_vtkh_data_adapter.cpp @@ -27,6 +27,9 @@ #include #endif +#include +#include + // VTKm includes #define VTKM_USE_DOUBLE_PRECISION #include diff --git a/src/libs/ascent/runtimes/expressions/ascent_array_internals.hpp b/src/libs/ascent/runtimes/expressions/ascent_array_internals.hpp index 24b1b3929..a896d9e37 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_array_internals.hpp +++ b/src/libs/ascent/runtimes/expressions/ascent_array_internals.hpp @@ -14,6 +14,7 @@ #include "ascent_memory_manager.hpp" #include "ascent_logging.hpp" +#include "ascent_logging_old.hpp" #if defined(ASCENT_UMPIRE_ENABLED) #include diff --git a/src/libs/ascent/runtimes/expressions/ascent_blueprint_type_utils.hpp b/src/libs/ascent/runtimes/expressions/ascent_blueprint_type_utils.hpp index 565df5011..ef47a2672 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_blueprint_type_utils.hpp +++ b/src/libs/ascent/runtimes/expressions/ascent_blueprint_type_utils.hpp @@ -9,6 +9,7 @@ #include #include +#include //----------------------------------------------------------------------------- // -- begin ascent:: -- diff --git a/src/libs/ascent/runtimes/expressions/ascent_execution_manager.cpp b/src/libs/ascent/runtimes/expressions/ascent_execution_manager.cpp index d204ea4fe..e2c547a46 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_execution_manager.cpp +++ b/src/libs/ascent/runtimes/expressions/ascent_execution_manager.cpp @@ -1,6 +1,7 @@ #include "ascent_execution_manager.hpp" #include #include +#include namespace ascent { diff --git a/src/libs/ascent/runtimes/expressions/ascent_jit_array.cpp b/src/libs/ascent/runtimes/expressions/ascent_jit_array.cpp index 61ac28a34..7d3245a05 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_jit_array.cpp +++ b/src/libs/ascent/runtimes/expressions/ascent_jit_array.cpp @@ -12,6 +12,7 @@ #include "ascent_jit_array.hpp" #include +#include //----------------------------------------------------------------------------- // -- begin ascent:: -- diff --git a/src/libs/ascent/runtimes/expressions/ascent_jit_field.cpp b/src/libs/ascent/runtimes/expressions/ascent_jit_field.cpp index ae2d082a5..09d3a6fe0 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_jit_field.cpp +++ b/src/libs/ascent/runtimes/expressions/ascent_jit_field.cpp @@ -12,6 +12,7 @@ #include "ascent_jit_field.hpp" #include +#include //----------------------------------------------------------------------------- // -- begin ascent:: -- diff --git a/src/libs/ascent/runtimes/expressions/ascent_jit_math.cpp b/src/libs/ascent/runtimes/expressions/ascent_jit_math.cpp index 9a734e8ec..a3ce2f859 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_jit_math.cpp +++ b/src/libs/ascent/runtimes/expressions/ascent_jit_math.cpp @@ -12,6 +12,7 @@ #include "ascent_jit_math.hpp" #include +#include //----------------------------------------------------------------------------- // -- begin ascent:: -- diff --git a/src/libs/ascent/runtimes/expressions/ascent_memory_manager.cpp b/src/libs/ascent/runtimes/expressions/ascent_memory_manager.cpp index aa988e1d0..e74e7038a 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_memory_manager.cpp +++ b/src/libs/ascent/runtimes/expressions/ascent_memory_manager.cpp @@ -1,5 +1,6 @@ #include "ascent_memory_manager.hpp" #include +#include #include diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_conduit_to_vtkm_parsing.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_conduit_to_vtkm_parsing.cpp index fc6e31a91..d4af2066b 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_conduit_to_vtkm_parsing.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_conduit_to_vtkm_parsing.cpp @@ -14,6 +14,7 @@ #include "ascent_runtime_conduit_to_vtkm_parsing.hpp" #include +#include using namespace conduit; //----------------------------------------------------------------------------- @@ -252,6 +253,7 @@ parse_color_table(const conduit::Node &color_table_node) const Node &peg = itr.next(); if(!peg.has_child("position")) { + // FIXME: This should be an error ASCENT_WARN("Color map control point must have a position"); } diff --git a/src/libs/ascent/utils/ascent_logging.cpp b/src/libs/ascent/utils/ascent_logging_old.cpp similarity index 94% rename from src/libs/ascent/utils/ascent_logging.cpp rename to src/libs/ascent/utils/ascent_logging_old.cpp index 016a27d20..88ee5330d 100644 --- a/src/libs/ascent/utils/ascent_logging.cpp +++ b/src/libs/ascent/utils/ascent_logging_old.cpp @@ -6,11 +6,11 @@ //----------------------------------------------------------------------------- /// -/// file: ascent_logging.cpp +/// file: ascent_logging_old.cpp /// //----------------------------------------------------------------------------- -#include "ascent_logging.hpp" +#include "ascent_logging_old.hpp" //----------------------------------------------------------------------------- // -- begin ascent:: -- diff --git a/src/libs/ascent/utils/ascent_logging.hpp b/src/libs/ascent/utils/ascent_logging_old.hpp similarity index 98% rename from src/libs/ascent/utils/ascent_logging.hpp rename to src/libs/ascent/utils/ascent_logging_old.hpp index 1e572188b..1df8e7dcb 100644 --- a/src/libs/ascent/utils/ascent_logging.hpp +++ b/src/libs/ascent/utils/ascent_logging_old.hpp @@ -9,8 +9,8 @@ /// file: ascent_logging.hpp /// //----------------------------------------------------------------------------- -#ifndef ASCENT_LOGGING_HPP -#define ASCENT_LOGGING_HPP +#ifndef ASCENT_LOGGING_OLD_HPP +#define ASCENT_LOGGING_OLD_HPP #include #include diff --git a/src/libs/logging/ascent_logging.cpp b/src/libs/logging/ascent_logging.cpp index ac4f2d82c..094f7d80d 100644 --- a/src/libs/logging/ascent_logging.cpp +++ b/src/libs/logging/ascent_logging.cpp @@ -235,7 +235,7 @@ Logger::log_message(int level, ... msg txt */ os << m_indent_string <<"-\n"; - os << m_indent_string << " level: " << level_string(level) << "\n"; + os << m_indent_string << " level: " << level_id_to_string(level) << "\n"; if(detailed) { os << m_indent_string << " file: " << file << "\n"; @@ -276,7 +276,7 @@ Logger::log_message(int level, ... msg txt */ os << m_indent_string <<"-\n"; - os << m_indent_string << " level: " << level_string(level) << "\n"; + os << m_indent_string << " level: " << level_id_to_string(level) << "\n"; if(detailed) { os << m_indent_string << " timestamp: \"" << timestamp() << "\"\n"; @@ -341,6 +341,13 @@ Logger::set_log_threshold(int level) m_log_threshold = level; } +//----------------------------------------------------------------------------- +void +Logger::set_log_threshold(const std::string &level_str) +{ + set_log_threshold(level_string_to_id(level_str)); +} + //----------------------------------------------------------------------------- int Logger::log_threshold() const @@ -355,6 +362,14 @@ Logger::set_echo_threshold(int level) m_echo_threshold = level; } +//----------------------------------------------------------------------------- +void +Logger::set_echo_threshold(const std::string &level_str) +{ + set_echo_threshold(level_string_to_id(level_str)); +} + + //----------------------------------------------------------------------------- int Logger::echo_threshold() const @@ -378,7 +393,7 @@ Logger::instance() //----------------------------------------------------------------------------- std::string -Logger::level_string(int level) +Logger::level_id_to_string(int level) { if(level < Logger::ALL ) { @@ -403,6 +418,42 @@ Logger::level_string(int level) } } +//----------------------------------------------------------------------------- +int +Logger::level_string_to_id(const std::string &level_str) +{ + // strip, lower? + if(level_str == "all" ) + { + return Logger::ALL; + } + else if(level_str == "debug" ) + { + return Logger::DEBUG; + } + else if(level_str == "info" ) + { + return Logger::INFO; + } + else if(level_str == "warn" ) + { + return Logger::WARN; + } + else if(level_str == "error" ) + { + return Logger::ERROR; + } + else if(level_str == "none" ) + { + return Logger::NONE; + } + else + { + // Unknown, default to all. + return Logger::ALL; + } +} + //----------------------------------------------------------------------------- std::string Logger::timestamp() diff --git a/src/libs/logging/ascent_logging.hpp b/src/libs/logging/ascent_logging.hpp index 4ae985427..759c63723 100644 --- a/src/libs/logging/ascent_logging.hpp +++ b/src/libs/logging/ascent_logging.hpp @@ -202,10 +202,12 @@ class ASCENT_API Logger // any msgs >= log_threshold will be logged void set_log_threshold(int level); + void set_log_threshold(const std::string &level_str); int log_threshold() const; // any msgs >= echo_threshold will sent to std out as well as log void set_echo_threshold(int level); + void set_echo_threshold(const std::string &level_str); int echo_threshold() const; std::ostream &log_stream(); @@ -221,7 +223,8 @@ class ASCENT_API Logger // ------------------------------------------------------------------------ // helpers // ------------------------------------------------------------------------ - static std::string level_string(int level); + static std::string level_id_to_string(int level); + static int level_string_to_id(const std::string &level_str); static std::string timestamp(); void log_message(int level, From 4b320c6d3386b3f951387f746e3605ac5b516825 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 9 Dec 2024 10:31:04 -0800 Subject: [PATCH 08/14] add test for logging --- src/libs/ascent/ascent.cpp | 13 +++++++++---- .../flow_filters/ascent_runtime_dray_filters.cpp | 1 + src/tests/ascent/CMakeLists.txt | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libs/ascent/ascent.cpp b/src/libs/ascent/ascent.cpp index c23fd0703..4f2b7092d 100644 --- a/src/libs/ascent/ascent.cpp +++ b/src/libs/ascent/ascent.cpp @@ -317,11 +317,11 @@ Ascent::open(const conduit::Node &options) Node logging_opts; logging_opts["enabled"] = 0; #if defined(ASCENT_MPI_ENABLED) - logging_opts["file_pattern"] = "ascent_log_output.yaml"; + logging_opts["file_pattern"] = "ascent_log_output_rank_{rank:05d}.yaml"; #else - logging_opts["file_pattern"] = "ascent_log_output_rank{rank:05d}.yaml"; + logging_opts["file_pattern"] = "ascent_log_output.yaml"; #endif - logging_opts["log_threshold"] = "info"; + logging_opts["log_threshold"] = "debug"; if(m_options.has_path("logging")) { @@ -345,7 +345,8 @@ Ascent::open(const conduit::Node &options) ASCENT_LOG_OPEN( file_pattern ) // serial #else ASCENT_LOG_OPEN_RANK( file_pattern, par_rank ) // mpi par - #endif + #endif + logger.set_log_threshold(logging_opts["log_threshold"].as_string()); } @@ -684,6 +685,7 @@ Ascent::close() } set_status("Ascent::close completed"); + ASCENT_LOG_CLOSE(); } catch(conduit::Error &e) { @@ -709,6 +711,7 @@ Ascent::close() << e.message() << std::endl; } } + ASCENT_LOG_CLOSE(); } } @@ -720,6 +723,7 @@ Ascent::set_status(const std::string &msg) std::ostringstream oss; oss << msg << " at " << timestamp(); m_status["message"] = oss.str(); + ASCENT_LOG_DEBUG(msg); } //---------------------------------------------------------------------------// @@ -732,6 +736,7 @@ Ascent::set_status(const std::string &msg, oss << msg << " at " << timestamp(); m_status["message"] = oss.str(); m_status["details"] = details; + ASCENT_LOG_DEBUG(msg + " " + details); } //---------------------------------------------------------------------------// diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp index 08eee01e5..309e0fd7f 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp @@ -451,6 +451,7 @@ parse_color_table(const conduit::Node &color_table_node) const Node &peg = itr.next(); if(!peg.has_child("position")) { + // FIXME: This should be an error ASCENT_WARN("Color map control point must have a position"); } diff --git a/src/tests/ascent/CMakeLists.txt b/src/tests/ascent/CMakeLists.txt index 7e2664116..c4bd7ce10 100644 --- a/src/tests/ascent/CMakeLists.txt +++ b/src/tests/ascent/CMakeLists.txt @@ -16,6 +16,7 @@ set(BASIC_TESTS t_ascent_smoke t_ascent_runtime_options t_ascent_data_binning t_ascent_utils + t_ascent_logging t_ascent_annotations t_ascent_derived t_ascent_empty_runtime From ffc94bb2096c26907afedb32a05622710fc80d4d Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 9 Dec 2024 10:36:31 -0800 Subject: [PATCH 09/14] add test srouce --- src/tests/ascent/t_ascent_logging.cpp | 151 ++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/tests/ascent/t_ascent_logging.cpp diff --git a/src/tests/ascent/t_ascent_logging.cpp b/src/tests/ascent/t_ascent_logging.cpp new file mode 100644 index 000000000..ba3e73820 --- /dev/null +++ b/src/tests/ascent/t_ascent_logging.cpp @@ -0,0 +1,151 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) Lawrence Livermore National Security, LLC and other Ascent +// Project developers. See top-level LICENSE AND COPYRIGHT files for dates and +// other details. No copyright assignment is required to contribute to Ascent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +//----------------------------------------------------------------------------- +/// +/// file: t_ascent_logging.cpp +/// +//----------------------------------------------------------------------------- + + +#include "gtest/gtest.h" + +#include + +#include +#include + +#include + +#include "t_config.hpp" +#include "t_utils.hpp" + + + + +using namespace std; +using namespace conduit; +using namespace ascent; + + + +//----------------------------------------------------------------------------- +TEST(ascent_logging, test_logging_simplest) +{ + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent vtkm support disabled, skipping test"); + return; + } + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + 5, + 5, + 5, + data); + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_logging_render1"); + + // remove old images before rendering + remove_test_image(output_file); + conduit::utils::remove_path_if_exists("ascent_log_output.yaml"); + EXPECT_FALSE(conduit::utils::is_file("ascent_log_output.yaml")); + + conduit::Node actions; + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + conduit::Node &scenes = add_scenes["scenes"]; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "braid"; + scenes["s1/image_prefix"] = output_file; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["logging"] = "true"; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that the log file exists + EXPECT_TRUE(conduit::utils::is_file("ascent_log_output.yaml")); + +} + +//----------------------------------------------------------------------------- +TEST(ascent_logging, test_logging_options) +{ + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent vtkm support disabled, skipping test"); + return; + } + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + 5, + 5, + 5, + data); + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_logging_render2"); + string log_file = conduit::utils::join_file_path(output_path,"tout_my_log.yaml"); + + // remove old images before rendering + remove_test_image(output_file); + conduit::utils::remove_path_if_exists(log_file); + EXPECT_FALSE(conduit::utils::is_file(log_file)); + + conduit::Node actions; + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + conduit::Node &scenes = add_scenes["scenes"]; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "braid"; + scenes["s1/image_prefix"] = output_file; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["logging/file_pattern"] = log_file; + ascent_opts["logging/log_threshold"] = "all"; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that the log file exists + EXPECT_TRUE(conduit::utils::is_file(log_file)); + +} \ No newline at end of file From d961df8c1bbb8cd225da1df266b6c1c4cd9c9a46 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Thu, 12 Dec 2024 09:50:32 -0800 Subject: [PATCH 10/14] prevent use of bad comm if user forgot to pass one --- src/libs/ascent/ascent.cpp | 12 ++++++++++++ src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/libs/ascent/ascent.cpp b/src/libs/ascent/ascent.cpp index 4f2b7092d..f8c9098dd 100644 --- a/src/libs/ascent/ascent.cpp +++ b/src/libs/ascent/ascent.cpp @@ -49,6 +49,12 @@ ParRank(int comm_id) int rank = 0; #if defined(ASCENT_MPI_ENABLED) + if(mpi_comm_id == -1) + { + // do nothing, an error will be thrown later + // so we can respect the exception handling + return 0; + } MPI_Comm mpi_comm = MPI_Comm_f2c(comm_id); MPI_Comm_rank(mpi_comm, &rank); #endif @@ -63,6 +69,12 @@ ParSize(int comm_id) int comm_size=1; #if defined(ASCENT_MPI_ENABLED) + if(mpi_comm_id == -1) + { + // do nothing, an error will be thrown later + // so we can respect the exception handling + return 1; + } MPI_Comm mpi_comm = MPI_Comm_f2c(comm_id); MPI_Comm_size(mpi_comm, &comm_size); #endif diff --git a/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp b/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp index 3ab6eb5cf..5cb08c702 100644 --- a/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp +++ b/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp @@ -124,7 +124,7 @@ TEST(ascent_mpi_runtime, test_error_for_mpi_vs_non_mpi) Ascent ascent; Node ascent_opts; ascent_opts["exceptions"] = "forward"; - // we throw an error if an mpi_comm is NO provided to a mpi ver of ascent + // we throw an error if an mpi_comm is NOT provided to a mpi ver of ascent EXPECT_THROW(ascent.open(ascent_opts),conduit::Error); } From 3bbe7ccbf081be66efae18ae5524cff060b88135 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Thu, 12 Dec 2024 12:11:53 -0800 Subject: [PATCH 11/14] windows fix and typo fix --- src/libs/ascent/ascent.cpp | 6 +-- src/libs/logging/ascent_logging.cpp | 50 ++++++++++----------- src/libs/logging/ascent_logging.hpp | 20 ++++----- src/tests/logging/t_ascent_logger_basic.cpp | 8 ++-- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/libs/ascent/ascent.cpp b/src/libs/ascent/ascent.cpp index f8c9098dd..8f77792b9 100644 --- a/src/libs/ascent/ascent.cpp +++ b/src/libs/ascent/ascent.cpp @@ -49,7 +49,7 @@ ParRank(int comm_id) int rank = 0; #if defined(ASCENT_MPI_ENABLED) - if(mpi_comm_id == -1) + if(comm_id == -1) { // do nothing, an error will be thrown later // so we can respect the exception handling @@ -69,7 +69,7 @@ ParSize(int comm_id) int comm_size=1; #if defined(ASCENT_MPI_ENABLED) - if(mpi_comm_id == -1) + if(comm_id == -1) { // do nothing, an error will be thrown later // so we can respect the exception handling @@ -313,7 +313,7 @@ Ascent::open(const conduit::Node &options) { if(par_rank != 0) { - logger.set_echo_threshold(ascent::Logger::NONE); + logger.set_echo_threshold("none"); } } diff --git a/src/libs/logging/ascent_logging.cpp b/src/libs/logging/ascent_logging.cpp index 094f7d80d..1c1131df6 100644 --- a/src/libs/logging/ascent_logging.cpp +++ b/src/libs/logging/ascent_logging.cpp @@ -55,8 +55,8 @@ Logger::Logger() : m_log_open(false), m_indent_level(0), m_rank(-1), - m_log_threshold(Logger::INFO), - m_echo_threshold(Logger::NONE) + m_log_threshold(Logger::LOG_INFO_ID), + m_echo_threshold(Logger::LOG_NONE_ID) { m_key_counters.push(std::map()); } @@ -72,8 +72,8 @@ void Logger::reset() { m_indent_level = 0; - m_log_threshold = Logger::INFO; - m_echo_threshold = Logger::NONE; + m_log_threshold = Logger::LOG_INFO_ID; + m_echo_threshold = Logger::LOG_NONE_ID; // reset our stacks m_timers = std::stack(); m_key_counters = std::stack>(); @@ -114,7 +114,7 @@ Logger::open(const std::string &ofpattern) __LINE__); } m_log_open = true; - log_message(Logger::DEBUG,conduit_fmt::format("opened log file: {}", m_log_fname)); + log_message(Logger::LOG_DEBUG_ID,conduit_fmt::format("opened log file: {}", m_log_fname)); } //----------------------------------------------------------------------------- @@ -130,7 +130,7 @@ Logger::close() { if(is_log_open()) { - log_message(Logger::DEBUG,conduit_fmt::format("closing log file: {}", m_log_fname)); + log_message(Logger::LOG_DEBUG_ID,conduit_fmt::format("closing log file: {}", m_log_fname)); m_log_stream.close(); m_log_open = false; m_log_fname = ""; @@ -395,26 +395,26 @@ Logger::instance() std::string Logger::level_id_to_string(int level) { - if(level < Logger::ALL ) + if(level < Logger::LOG_ALL_ID ) { - level = Logger::ALL; + level = Logger::LOG_ALL_ID; } - else if(level < Logger::DEBUG) + else if(level < Logger::LOG_DEBUG_ID) { - level = Logger::DEBUG; + level = Logger::LOG_DEBUG_ID; } - else if(level > Logger::ERROR) + else if(level > Logger::LOG_ERROR_ID) { - level = Logger::NONE; + level = Logger::LOG_ERROR_ID; } switch(level) { - case Logger::ALL: return "all"; break; - case Logger::DEBUG: return "debug"; break; - case Logger::INFO: return "info"; break; - case Logger::WARN: return "warn"; break; - case Logger::ERROR: return "error"; break; - case Logger::NONE: return "none"; break; + case Logger::LOG_ALL_ID: return "all"; break; + case Logger::LOG_DEBUG_ID: return "debug"; break; + case Logger::LOG_INFO_ID: return "info"; break; + case Logger::LOG_WARN_ID: return "warn"; break; + case Logger::LOG_ERROR_ID: return "error"; break; + case Logger::LOG_NONE_ID: return "none"; break; } } @@ -425,32 +425,32 @@ Logger::level_string_to_id(const std::string &level_str) // strip, lower? if(level_str == "all" ) { - return Logger::ALL; + return Logger::LOG_ALL_ID; } else if(level_str == "debug" ) { - return Logger::DEBUG; + return Logger::LOG_DEBUG_ID; } else if(level_str == "info" ) { - return Logger::INFO; + return Logger::LOG_INFO_ID; } else if(level_str == "warn" ) { - return Logger::WARN; + return Logger::LOG_WARN_ID; } else if(level_str == "error" ) { - return Logger::ERROR; + return Logger::LOG_ERROR_ID; } else if(level_str == "none" ) { - return Logger::NONE; + return Logger::LOG_NONE_ID; } else { // Unknown, default to all. - return Logger::ALL; + return Logger::LOG_ALL_ID; } } diff --git a/src/libs/logging/ascent_logging.hpp b/src/libs/logging/ascent_logging.hpp index 759c63723..84cba5263 100644 --- a/src/libs/logging/ascent_logging.hpp +++ b/src/libs/logging/ascent_logging.hpp @@ -65,7 +65,7 @@ ASCENT_LOG_CLOSE() { \ std::ostringstream _ascent_oss_info; \ _ascent_oss_info << msg; \ - ascent::Logger::instance().log_message(ascent::Logger::DEBUG, \ + ascent::Logger::instance().log_message(ascent::Logger::LOG_DEBUG_ID, \ _ascent_oss_info.str(), \ std::string(__FILE__), \ __LINE__); \ @@ -76,7 +76,7 @@ ASCENT_LOG_CLOSE() { \ std::ostringstream _ascent_oss_info; \ _ascent_oss_info << msg; \ - ascent::Logger::instance().log_message(ascent::Logger::INFO, \ + ascent::Logger::instance().log_message(ascent::Logger::LOG_INFO_ID, \ _ascent_oss_info.str(), \ std::string(__FILE__), \ __LINE__); \ @@ -87,7 +87,7 @@ ASCENT_LOG_CLOSE() { \ std::ostringstream _ascent_oss_info; \ _ascent_oss_info << msg; \ - ascent::Logger::instance().log_message(ascent::Logger::WARN, \ + ascent::Logger::instance().log_message(ascent::Logger::LOG_WARN_ID, \ _ascent_oss_info.str(), \ std::string(__FILE__), \ __LINE__); \ @@ -98,7 +98,7 @@ ASCENT_LOG_CLOSE() { \ std::ostringstream _ascent_oss_info; \ _ascent_oss_info << msg; \ - ascent::Logger::instance().log_message(ascent::Logger::ERROR, \ + ascent::Logger::instance().log_message(ascent::Logger::LOG_ERROR_ID, \ _ascent_oss_info.str(), \ std::string(__FILE__), \ __LINE__); \ @@ -152,12 +152,12 @@ class ASCENT_API Logger //------------------------------------------------------------------------- typedef enum { - ALL = -1, // lowest - DEBUG = 1, - INFO = 2, - WARN = 3, - ERROR = 4, - NONE = 127, // highest + LOG_ALL_ID = -1, // lowest + LOG_DEBUG_ID = 1, + LOG_INFO_ID = 2, + LOG_WARN_ID = 3, + LOG_ERROR_ID = 4, + LOG_NONE_ID = 127, // highest } MessageLevel; //------------------------------------------------------------------------- diff --git a/src/tests/logging/t_ascent_logger_basic.cpp b/src/tests/logging/t_ascent_logger_basic.cpp index e6eaa02d6..8d93416b5 100644 --- a/src/tests/logging/t_ascent_logger_basic.cpp +++ b/src/tests/logging/t_ascent_logger_basic.cpp @@ -91,7 +91,7 @@ TEST(ascent_logging, basic_logging_echo) // remove file if it exists std::string lfname = "tout_logging_log_2.yaml"; conduit::utils::remove_path_if_exists(lfname); - ascent::Logger::instance().set_echo_threshold(ascent::Logger::ALL); + ascent::Logger::instance().set_echo_threshold(ascent::Logger::LOG_ALL_ID); std::cout << "[echoed]" << std::endl; ASCENT_LOG_OPEN(lfname); ASCENT_LOG_DEBUG("my debug!"); @@ -115,7 +115,7 @@ TEST(ascent_logging, basic_logging_threshold) conduit::utils::remove_path_if_exists(lfname); ASCENT_LOG_OPEN(lfname); ASCENT_LOG_INFO("my info!"); - ascent::Logger::instance().set_log_threshold(ascent::Logger::NONE); + ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_NONE_ID); ASCENT_LOG_WARN("my warning!"); ASCENT_LOG_CLOSE(); @@ -175,14 +175,14 @@ TEST(ascent_logging, basic_logging_append) // remove file if it exists std::string lfname = "tout_logging_log_5.yaml"; conduit::utils::remove_path_if_exists(lfname); - ascent::Logger::instance().set_log_threshold(ascent::Logger::ALL); + ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_ALL_ID); ASCENT_LOG_OPEN(lfname); ASCENT_LOG_INFO("my debug 1!"); ASCENT_LOG_INFO("my info 1!"); ASCENT_LOG_WARN("my warning 1!"); ASCENT_LOG_CLOSE(); - ascent::Logger::instance().set_log_threshold(ascent::Logger::ALL); + ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_ALL_ID); ASCENT_LOG_OPEN(lfname); ASCENT_LOG_INFO("my debug 2!"); ASCENT_LOG_INFO("my info 2!"); From 6555bcfabb27444809baa7cc002b61ade412da65 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Fri, 13 Dec 2024 13:19:03 -0800 Subject: [PATCH 12/14] add ascent_logging lib to mk config --- src/config/ascent_config.mk.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/config/ascent_config.mk.in b/src/config/ascent_config.mk.in index 266e1ec2b..d1cdced9f 100644 --- a/src/config/ascent_config.mk.in +++ b/src/config/ascent_config.mk.in @@ -302,6 +302,7 @@ ASCENT_LIB_FLAGS = $(ASCENT_DEVICE_OBJECT) \ -lascent \ -lascent_flow \ -lascent_lodepng \ + -lascent_logging \ $(ASCENT_ROVER_LIB_FLAGS) $(DRAY_LIB_FLAGS) $(ASCENT_VTKH_LIB_FLAGS) $(ASCENT_VTKM_LIB_FLAGS) $(VTKH_LIB_FLAGS) $(ASCENT_CONDUIT_LIB_FLAGS) $(ASCENT_MFEM_LIB_FLAGS) $(ASCENT_RAJA_LIB_FLAGS) $(ASCENT_UMPIRE_LIB_FLAGS) $(ASCENT_CAMP_LIB_FLAGS) $(ASCENT_OCCA_LIB_FLAGS) $(ASCENT_GENTEN_LIB_FLAGS) $(ASCENT_PYTHON_LIBS) $(ASCENT_CALIPER_LIB_FLAGS) $(ASCENT_ADIAK_LIB_FLAGS) $(ASCENT_OPENMP_LINK_FLAGS) $(ASCENT_CUDA_LIB_FLAGS) # if using Ascent with mpi and/or cuda with a non-GPU sim @@ -310,6 +311,7 @@ ASCENT_MPI_LIB_FLAGS = $(ASCENT_DEVICE_OBJECT_MPI) \ -lascent_mpi \ -lascent_flow \ -lascent_lodepng \ + -lascent_logging \ $(ASCENT_ROVER_MPI_LIB_FLAGS) $(DRAY_MPI_LIB_FLAGS) $(ASCENT_VTKH_MPI_LIB_FLAGS) $(ASCENT_VTKM_LIB_FLAGS) $(VTKH_MPI_LIB_FLAGS) $(ASCENT_CONDUIT_MPI_LIB_FLAGS) $(ASCENT_MFEM_LIB_FLAGS) $(ASCENT_FIDES_LIB_FLAGS) $(ASCENT_ADIOS2_LIB_FLAGS) $(ASCENT_PMT_LIB_FLAGS) $(ASCENT_STREAMSTAT_LIB_FLAGS) $(ASCENT_TOPOFILEPARSER_LIB_FLAGS) $(ASCENT_BABELFLOW_LIB_FLAGS) $(ASCENT_RAJA_LIB_FLAGS) $(ASCENT_UMPIRE_LIB_FLAGS) $(ASCENT_CAMP_LIB_FLAGS) $(ASCENT_OCCA_LIB_FLAGS) $(ASCENT_GENTEN_LIB_FLAGS) $(ASCENT_PYTHON_LIBS) $(ASCENT_CALIPER_LIB_FLAGS) $(ASCENT_OPENMP_LINK_FLAGS) $(ASCENT_CUDA_LIB_FLAGS) @@ -319,5 +321,6 @@ ASCENT_MPI_CUDA_LIB_FLAGS = -L $(ASCENT_DIR)/lib \ -lascent_mpi \ -lascent_flow \ -lascent_lodepng \ + -lascent_logging \ $(ASCENT_ROVER_MPI_LIB_FLAGS) $(DRAY_MPI_LIB_FLAGS) $(ASCENT_VTKH_MPI_LIB_FLAGS) $(ASCENT_VTKM_LIB_FLAGS) $(VTKH_MPI_LIB_FLAGS) $(ASCENT_CONDUIT_MPI_LIB_FLAGS) $(ASCENT_MFEM_LIB_FLAGS) $(ASCENT_OCCA_LIB_FLAGS) $(ASCENT_GENTEN_LIB_FLAGS) $(ASCENT_FIDES_LIB_FLAGS) $(ASCENT_ADIOS2_LIB_FLAGS) $(ASCENT_PMT_LIB_FLAGS) $(ASCENT_STREAMSTAT_LIB_FLAGS) $(ASCENT_TOPOFILEPARSER_LIB_FLAGS) $(ASCENT_BABELFLOW_LIB_FLAGS) $(ASCENT_RAJA_LIB_FLAGS) $(ASCENT_UMPIRE_LIB_FLAGS) $(ASCENT_CAMP_LIB_FLAGS) $(ASCENT_PYTHON_LIBS) $(ASCENT_CALIPER_LIB_FLAGS) $(ASCENT_OPENMP_LINK_FLAGS) $(ASCENT_CUDA_LIB_FLAGS) From 5075f20e5369dfde4d6815b0bc5c90ff6e657f9e Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Fri, 13 Dec 2024 15:37:44 -0800 Subject: [PATCH 13/14] msg and log rank options and mpi log tests --- src/libs/ascent/ascent.cpp | 76 +++++++++++++-- .../ascent/t_ascent_mpi_ascent_runtime.cpp | 93 +++++++++++++++++++ 2 files changed, 163 insertions(+), 6 deletions(-) diff --git a/src/libs/ascent/ascent.cpp b/src/libs/ascent/ascent.cpp index 8f77792b9..100561909 100644 --- a/src/libs/ascent/ascent.cpp +++ b/src/libs/ascent/ascent.cpp @@ -302,20 +302,43 @@ Ascent::open(const conduit::Node &options) // setup echo logger.set_echo_threshold(echo_opts["echo_threshold"].as_string()); - // control for mpi case + // controls for mpi ranks // if ranks == "root" // rank 0 is what is specified, echo_threshold = "none" for all others // if ranks == "all" // echo_threshold = specified option used for all ranks (alreay handled above) - std::string log_ranks_str = echo_opts["ranks"].as_string(); + // if ranks == [list of ints] (also accepts single int) + // echo_threshold = specified option used for ranks in the list - if(log_ranks_str == "root") + if(echo_opts["ranks"].dtype().is_number()) // list of ints case { - if(par_rank != 0) + int64_accessor ranks_list = echo_opts["ranks"].value(); + bool active = false; + for(index_t i=0; i < ranks_list.number_of_elements(); i++) + { + if(par_rank == ranks_list[i] ) + { + active = true; + } + } + + if(!active) { logger.set_echo_threshold("none"); } } + else // string options case + { + std::string log_ranks_str = echo_opts["ranks"].as_string(); + + if(log_ranks_str == "root") + { + if(par_rank != 0) + { + logger.set_echo_threshold("none"); + } + } + } // logging options // @@ -328,6 +351,7 @@ Ascent::open(const conduit::Node &options) Node logging_opts; logging_opts["enabled"] = 0; + logging_opts["ranks"] = "all"; #if defined(ASCENT_MPI_ENABLED) logging_opts["file_pattern"] = "ascent_log_output_rank_{rank:05d}.yaml"; #else @@ -350,13 +374,53 @@ Ascent::open(const conduit::Node &options) } } + // controls for mpi ranks + // if ranks == "root" + // open log on rank 0, do not open on all others + // if ranks == "all" + // open log on all ranks + // if ranks == [list of ints] (also accepts single int) + // open log on ranks specified in the list + + if(logging_opts["ranks"].dtype().is_number()) // list of ints case + { + int64_accessor ranks_list = logging_opts["ranks"].value(); + bool active = false; + for(index_t i=0; i < ranks_list.number_of_elements(); i++) + { + if(par_rank == ranks_list[i] ) + { + active = true; + } + } + + if(!active) + { + logging_opts["enabled"] = 0; + } + } + else // string options case + { + std::string log_ranks_str = logging_opts["ranks"].as_string(); + + if(log_ranks_str == "root") + { + if(par_rank != 0) + { + logging_opts["enabled"] = 0; + } + } + // all already supported if logging is enabled + } + + if(logging_opts["enabled"].to_int() == 1) { std::string file_pattern = logging_opts["file_pattern"].as_string(); #if defined(ASCENT_MPI_ENABLED) - ASCENT_LOG_OPEN( file_pattern ) // serial - #else ASCENT_LOG_OPEN_RANK( file_pattern, par_rank ) // mpi par + #else + ASCENT_LOG_OPEN( file_pattern ) // serial #endif logger.set_log_threshold(logging_opts["log_threshold"].as_string()); } diff --git a/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp b/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp index 5cb08c702..8232b4b1d 100644 --- a/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp +++ b/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp @@ -169,6 +169,99 @@ TEST(ascent_mpi_runtime, test_for_error_reading_actions) } +//----------------------------------------------------------------------------- +TEST(ascent_mpi_runtime, test_mpi_logs) +{ + // + // Set Up MPI + // + int par_rank; + int par_size; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Comm_rank(comm, &par_rank); + MPI_Comm_size(comm, &par_size); + + // make sure the _output dir exists + string output_path = ""; + if(par_rank == 0) + { + output_path = prepare_output_dir(); + } + else + { + output_path = output_dir(); + } + + string log_base = conduit::utils::join_file_path(output_path,"tout_log_mpi_test"); + + // + // Test cases + // + // case "0" creates 1 log per mpi task default name in cwd + // ascent_log_out_rank_00000.yaml + // ascent_log_out_rank_00001.yaml + // case "a" creates 1 log per mpi + // tout_log_mpi_test_rank_a_00.yaml + // tout_log_mpi_test_rank_a_01.yaml + // + // case "b" creates log only for root (rank 0) + // tout_log_mpi_test_rank_b_00.yaml + // + // case "c" creates log only on rank 1 + // tout_log_mpi_test_rank_c_01.yaml + // + + + if(par_rank == 0) + { + conduit::utils::remove_path_if_exists("ascent_log_output_rank_00000.yaml"); + conduit::utils::remove_path_if_exists("ascent_log_output_rank_00001.yaml"); + conduit::utils::remove_path_if_exists(log_base + "_a_00.yaml"); + conduit::utils::remove_path_if_exists(log_base + "_a_01.yaml"); + conduit::utils::remove_path_if_exists(log_base + "_b_00.yaml"); + conduit::utils::remove_path_if_exists(log_base + "_c_01.yaml"); + } + + Ascent ascent; + // case 0 + Node ascent_opts; + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent_opts["logging"] = "true"; + ascent.open(ascent_opts); + ascent.close(); + + // case a + ascent_opts.reset(); + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent_opts["logging/file_pattern"] = log_base + "_a_{rank:02d}.yaml"; + ascent.open(ascent_opts); + ascent.close(); + + // case b + ascent_opts.reset(); + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent_opts["logging/file_pattern"] = log_base + "_b_{rank:02d}.yaml"; + ascent_opts["logging/ranks"] = "root"; + ascent.open(ascent_opts); + ascent.close(); + + // case c + ascent_opts.reset(); + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent_opts["logging/file_pattern"] = log_base + "_c_{rank:02d}.yaml"; + ascent_opts["logging/ranks"] =1; + ascent.open(ascent_opts); + ascent.close(); + + MPI_Barrier(comm); + EXPECT_TRUE(conduit::utils::is_file("ascent_log_output_rank_00000.yaml")); + EXPECT_TRUE(conduit::utils::is_file("ascent_log_output_rank_00001.yaml")); + EXPECT_TRUE(conduit::utils::is_file(log_base + "_a_00.yaml")); + EXPECT_TRUE(conduit::utils::is_file(log_base + "_a_01.yaml")); + EXPECT_TRUE(conduit::utils::is_file(log_base + "_b_00.yaml")); + EXPECT_TRUE(conduit::utils::is_file(log_base + "_c_01.yaml")); +} + //----------------------------------------------------------------------------- int main(int argc, char* argv[]) From 8bfc3f0b8fe737b7c7a4a674c517b6e78680cf21 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 16 Dec 2024 16:05:17 -0800 Subject: [PATCH 14/14] address comments and a few tweaks --- CHANGELOG.md | 4 +++- src/libs/ascent/ascent.cpp | 10 +++++++++- src/tests/logging/t_ascent_logger_basic.cpp | 16 +++++++++------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25d41dc1b..0860caf66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,11 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s - raja@2024.02.1 - umpire@2024.02.1 - camp@2024.02.1 -- kokkos@3.7.02 +- kokkos@4.4.1 +- mfem@4.7 ### Added +- Added a new unified logging infrastructure. - Added support for unstructured topologies with mixed elements types (for example, hexs and tets). - Added support for `pyramid` and `wedge` elements. - Added `sphere`, `cylinder`, `box`, and `plane` options to the slice filter. diff --git a/src/libs/ascent/ascent.cpp b/src/libs/ascent/ascent.cpp index 100561909..3f48a52f2 100644 --- a/src/libs/ascent/ascent.cpp +++ b/src/libs/ascent/ascent.cpp @@ -23,10 +23,14 @@ #include #include +#include + #if defined(ASCENT_VTKH_ENABLED) #include #endif + + #ifdef ASCENT_MPI_ENABLED #include #include @@ -416,13 +420,17 @@ Ascent::open(const conduit::Node &options) if(logging_opts["enabled"].to_int() == 1) { + logger.set_log_threshold(logging_opts["log_threshold"].as_string()); std::string file_pattern = logging_opts["file_pattern"].as_string(); #if defined(ASCENT_MPI_ENABLED) ASCENT_LOG_OPEN_RANK( file_pattern, par_rank ) // mpi par + ASCENT_LOG_DEBUG(conduit_fmt::format("mpi info: rank={}, size={}", + par_rank, + par_size)); #else ASCENT_LOG_OPEN( file_pattern ) // serial + ASCENT_LOG_DEBUG("mpi not enabled"); #endif - logger.set_log_threshold(logging_opts["log_threshold"].as_string()); } diff --git a/src/tests/logging/t_ascent_logger_basic.cpp b/src/tests/logging/t_ascent_logger_basic.cpp index 8d93416b5..6baa9d665 100644 --- a/src/tests/logging/t_ascent_logger_basic.cpp +++ b/src/tests/logging/t_ascent_logger_basic.cpp @@ -61,20 +61,21 @@ TEST(ascent_logging, basic_logging) std::string lfname = "tout_logging_log_1.yaml"; conduit::utils::remove_path_if_exists(lfname); ASCENT_LOG_OPEN(lfname); + // top level entry count ASCENT_LOG_DEBUG("my debug!"); - ASCENT_LOG_INFO("my info!"); - ASCENT_LOG_WARN("my warning!"); - ASCENT_MARK_BEGIN("blocky"); + ASCENT_LOG_INFO("my info!"); // msg (1) + ASCENT_LOG_WARN("my warning!"); // msg (2) + ASCENT_MARK_BEGIN("blocky"); // block (3) ASCENT_LOG_INFO("my info!"); ASCENT_LOG_WARN("my warning!"); ASCENT_MARK_END("blocky"); - myfunc(); + myfunc(); // myfunc (4) - ASCENT_MARK_BEGIN("blocky"); + ASCENT_MARK_BEGIN("blocky"); // block (5) myfunc(); ASCENT_MARK_END("blocky"); - ASCENT_MARK_BEGIN("blocky"); + ASCENT_MARK_BEGIN("blocky"); // block (6) my_func_nest_0(); ASCENT_MARK_END("blocky"); ASCENT_LOG_CLOSE(); @@ -82,7 +83,8 @@ TEST(ascent_logging, basic_logging) conduit::Node n; n.load(lfname); n.print(); - + // 7 messages at root level + EXPECT_EQ(n.number_of_children(),6); } //-----------------------------------------------------------------------------