From 5086abb024bf2e34ce7be4e2b208bf48d58970d9 Mon Sep 17 00:00:00 2001 From: Emily Howell Date: Tue, 14 Jan 2025 16:11:37 -0800 Subject: [PATCH 1/7] Adding actions for opening, flushing, and closing the logs --- .../ascent/runtimes/ascent_main_runtime.cpp | 22 ++++++ src/tests/ascent/t_ascent_logging.cpp | 72 +++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/libs/ascent/runtimes/ascent_main_runtime.cpp b/src/libs/ascent/runtimes/ascent_main_runtime.cpp index 83c1dabc0..e454d003e 100644 --- a/src/libs/ascent/runtimes/ascent_main_runtime.cpp +++ b/src/libs/ascent/runtimes/ascent_main_runtime.cpp @@ -12,6 +12,7 @@ //----------------------------------------------------------------------------- #include "ascent_main_runtime.hpp" +#include // standard lib includes #include @@ -1936,6 +1937,27 @@ AscentRuntime::BuildGraph(const conduit::Node &actions) // the workspace executes. m_save_info_actions.append() = action; } + else if(action_name == "open_log") + { + // Open Ascent Logging Stream + // This starts logging + ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_ALL_ID); + std::string file_pattern = action.has_path("file_pattern") ? + action["file_pattern"].as_string() : "ascent_log_output.yaml"; + ASCENT_LOG_OPEN(file_pattern); + } + else if(action_name == "flush_log") + { + // Flush Current Log Streams to Disk + // This is so they can be seen before ascent is closed out + ASCENT_LOG_FLUSH(); + } + else if(action_name == "close_log") + { + // Closes current log stream + // This stops logging + ASCENT_LOG_CLOSE(); + } else { ASCENT_ERROR("Unknown action ' "< Date: Tue, 14 Jan 2025 16:51:07 -0800 Subject: [PATCH 2/7] Adding a contents check for the log file --- src/tests/ascent/t_ascent_logging.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tests/ascent/t_ascent_logging.cpp b/src/tests/ascent/t_ascent_logging.cpp index 3a55a4279..a247897e2 100644 --- a/src/tests/ascent/t_ascent_logging.cpp +++ b/src/tests/ascent/t_ascent_logging.cpp @@ -220,4 +220,9 @@ TEST(ascent_logging, test_logging_actions) // check that the log file exists EXPECT_TRUE(conduit::utils::is_file(log_file)); + + // check that the log file has the expected number of logs in it (1 open, 3 execution, 1 close) + conduit::Node log_file_contents; + log_file_contents.load(log_file); + EXPECT_EQ(log_file_contents.number_of_children(), 5); } \ No newline at end of file From fd260e8019dc6e56db3080d423cf4ca7c39a1f8a Mon Sep 17 00:00:00 2001 From: Emily Howell Date: Tue, 14 Jan 2025 17:06:57 -0800 Subject: [PATCH 3/7] Adding actions for adjusting the logging and echo thresholds --- .../ascent/runtimes/ascent_main_runtime.cpp | 26 +++++- src/tests/ascent/t_ascent_logging.cpp | 82 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/src/libs/ascent/runtimes/ascent_main_runtime.cpp b/src/libs/ascent/runtimes/ascent_main_runtime.cpp index e454d003e..f94dca2e4 100644 --- a/src/libs/ascent/runtimes/ascent_main_runtime.cpp +++ b/src/libs/ascent/runtimes/ascent_main_runtime.cpp @@ -1941,7 +1941,7 @@ AscentRuntime::BuildGraph(const conduit::Node &actions) { // Open Ascent Logging Stream // This starts logging - ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_ALL_ID); + ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_DEBUG_ID); std::string file_pattern = action.has_path("file_pattern") ? action["file_pattern"].as_string() : "ascent_log_output.yaml"; ASCENT_LOG_OPEN(file_pattern); @@ -1952,6 +1952,30 @@ AscentRuntime::BuildGraph(const conduit::Node &actions) // This is so they can be seen before ascent is closed out ASCENT_LOG_FLUSH(); } + else if(action_name == "set_log_threshold") + { + // Change the logging level + if (action.has_path("log_threshold")) + { + ascent::Logger::instance().set_log_threshold(action["log_threshold"].as_string()); + } + else + { + ASCENT_WARN("No Log Threshold level given. No changes to logging behavior made."); + } + } + else if(action_name == "set_echo_threshold") + { + // Change the echo to standard output level + if (action.has_path("echo_threshold")) + { + ascent::Logger::instance().set_log_threshold(action["echo_threshold"].as_string()); + } + else + { + ASCENT_WARN("No Echo Threshold level given. No changes to echo output behavior made."); + } + } else if(action_name == "close_log") { // Closes current log stream diff --git a/src/tests/ascent/t_ascent_logging.cpp b/src/tests/ascent/t_ascent_logging.cpp index a247897e2..3ae46676e 100644 --- a/src/tests/ascent/t_ascent_logging.cpp +++ b/src/tests/ascent/t_ascent_logging.cpp @@ -225,4 +225,86 @@ TEST(ascent_logging, test_logging_actions) conduit::Node log_file_contents; log_file_contents.load(log_file); EXPECT_EQ(log_file_contents.number_of_children(), 5); +} + +TEST(ascent_logging, test_logging_actions_threshold) +{ + 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_render4"); + string log_file = conduit::utils::join_file_path(output_path,"ascent_action_log_thresholded.yaml"); + + // remove old images/log files 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; + + conduit::Node actions_begin_logs; + conduit::Node &begin_logs= actions_begin_logs.append(); + begin_logs["action"] = "open_log"; + begin_logs["file_pattern"] = log_file; + conduit::Node &set_threshold_logs_open= actions_begin_logs.append(); + set_threshold_logs_open["action"] = "set_log_threshold"; + set_threshold_logs_open["log_threshold"] = "error"; + + conduit::Node actions_flush_logs; + conduit::Node &flush_logs= actions_flush_logs.append(); + flush_logs["action"] = "flush_log"; + + conduit::Node actions_close_logs; + conduit::Node &set_threshold_logs_close= actions_close_logs.append(); + set_threshold_logs_close["action"] = "set_log_threshold"; + set_threshold_logs_close["log_threshold"] = "debug"; + conduit::Node &close_logs= actions_close_logs.append(); + close_logs["action"] = "close_log"; + + // + // Run Ascent + // + + Ascent ascent; + + ascent.open(); + ascent.publish(data); + ascent.execute(actions_begin_logs); + ascent.execute(actions); + ascent.execute(actions_flush_logs); + ascent.execute(actions_close_logs); + ascent.close(); + + // check that the log file exists + EXPECT_TRUE(conduit::utils::is_file(log_file)); + + // check that the log file has the expected number of logs in it (1 open, 3 execution, 1 close) + conduit::Node log_file_contents; + log_file_contents.load(log_file); + EXPECT_EQ(log_file_contents.number_of_children(), 2); } \ No newline at end of file From 5e48d68828d6c217e3cbd1ed366157cfbfcfb1bb Mon Sep 17 00:00:00 2001 From: Emily Howell Date: Wed, 15 Jan 2025 12:58:40 -0800 Subject: [PATCH 4/7] Log threshold should have been echo threshold --- src/libs/ascent/runtimes/ascent_main_runtime.cpp | 2 +- src/tests/ascent/t_ascent_logging.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ascent/runtimes/ascent_main_runtime.cpp b/src/libs/ascent/runtimes/ascent_main_runtime.cpp index f94dca2e4..b54f44625 100644 --- a/src/libs/ascent/runtimes/ascent_main_runtime.cpp +++ b/src/libs/ascent/runtimes/ascent_main_runtime.cpp @@ -1969,7 +1969,7 @@ AscentRuntime::BuildGraph(const conduit::Node &actions) // Change the echo to standard output level if (action.has_path("echo_threshold")) { - ascent::Logger::instance().set_log_threshold(action["echo_threshold"].as_string()); + ascent::Logger::instance().set_echo_threshold(action["echo_threshold"].as_string()); } else { diff --git a/src/tests/ascent/t_ascent_logging.cpp b/src/tests/ascent/t_ascent_logging.cpp index 3ae46676e..1dc7b1138 100644 --- a/src/tests/ascent/t_ascent_logging.cpp +++ b/src/tests/ascent/t_ascent_logging.cpp @@ -307,4 +307,4 @@ TEST(ascent_logging, test_logging_actions_threshold) conduit::Node log_file_contents; log_file_contents.load(log_file); EXPECT_EQ(log_file_contents.number_of_children(), 2); -} \ No newline at end of file +} From 4a123706b9619be3a1ba266fce5244d95a8524d4 Mon Sep 17 00:00:00 2001 From: Emily Howell Date: Thu, 16 Jan 2025 15:42:39 -0800 Subject: [PATCH 5/7] Adding some basic documentation of the new logging actions --- CHANGELOG.md | 1 + src/docs/sphinx/Actions/Actions.rst | 5 ++ src/docs/sphinx/Actions/Logging.rst | 85 +++++++++++++++++++++++++++++ src/docs/sphinx/Actions/index.rst | 1 + 4 files changed, 92 insertions(+) create mode 100644 src/docs/sphinx/Actions/Logging.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index 0860caf66..2abd4c2f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s - mfem@4.7 ### Added +- Added action options relating to logging functionality including `open_log`, `flush_log`, and `close_log` to toggle logging as well as `set_log_threshold` and `set_echo_threshold` to control logging and standard output levels. - 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. diff --git a/src/docs/sphinx/Actions/Actions.rst b/src/docs/sphinx/Actions/Actions.rst index cd8dd73f3..d122f8a75 100644 --- a/src/docs/sphinx/Actions/Actions.rst +++ b/src/docs/sphinx/Actions/Actions.rst @@ -19,6 +19,11 @@ The currently supported actions are: - ``add_triggers`` : adds a list of triggers that executes a set of actions based on a condition - ``save_info`` : saves ascent info result at the end of execution - ``save_session`` : saves expression session info at the end of execution (see :ref:`ExpressionsSaveSession`) +- ``open_log`` : opens an assent logging stream and starts logging +- ``flush_log`` : flushes the current logging stream to the output file +- ``close_log`` : closes the current logging stream which stops logging +- ``set_log_threshold`` : changes the threshold of messages recorded in the log file +- ``set_echo_threshold`` : changes the threshold of messages displayed in standard output Ascent actions can be specified within the integration using Conduit Nodes and can be read in through a file. diff --git a/src/docs/sphinx/Actions/Logging.rst b/src/docs/sphinx/Actions/Logging.rst new file mode 100644 index 000000000..3437a6abd --- /dev/null +++ b/src/docs/sphinx/Actions/Logging.rst @@ -0,0 +1,85 @@ +.. ############################################################################ +.. # 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. +.. ############################################################################ + +.. _Logging: + +Logging Overview +================ + +Ascent's logging options allow for control over the types of messages and information that are +recorded and displayed. These functionalities are provided to allow for additional information to +be recorded while the tool is being run in order to identify and diagnose any erroneous behavior. + +The ``log`` options refer to the messages that are collected in a designated log stream and output +to a designated log file. The ``echo`` options control the messages and types of information output +to the standard output stream. + +Log Levels: +- ``all`` : all messages will be recorded +- ``debug`` : extra verbose output messages useful for diagnosing issues +- ``info`` : normal system operations +- ``warn`` : potential issues that could become a problem +- ``error`` : significant issues that need to be addressed +- ``none`` : no messages will be recorded. + +Opening Logs +------------ + +The ``open_log`` action can be used to start a logging stream. While there are no required keywords, +options to set the output log file name and location using the ``file_pattern`` keyword as well as +the logging threshold level using the ``log_threshold`` are available. The Default ``file_pattern`` +is ``ascent_log_output.yaml`` and the default ``log_threshold`` is ``debug``. + +.. code-block:: yaml + + - + action: "open_log" + file_pattern: "ascent_log_out_{rank:05d}.yaml" + log_threshold: "debug" + +Flushing Logs +------------- + +The ``flush_log`` action can be used to flush the current log streams to disk. + +.. code-block:: yaml + + - + action: "flush_log" + +Closing Logs +------------ + +The ``close_log`` action can be used to close the current log stream. + +.. code-block:: yaml + + - + action: "close_log" + +Setting the Logging Threshold +----------------------------- + +The ``set_log_threshold`` action allows for the adjustment of the level of log messages being +recorded to the current log stream. + +.. code-block:: yaml + + - + action: "set_log_threshold" + log_threshold: "all" + +Setting the Echo Threshold +----------------------------- + +The ``set_echo_threshold`` action allows for the adjustment of the level of log messages being +recorded to the standard output stream. + +.. code-block:: yaml + + - + action: "set_echo_threshold" + echo_threshold: "info" diff --git a/src/docs/sphinx/Actions/index.rst b/src/docs/sphinx/Actions/index.rst index 94b3e0d2b..09261aa31 100644 --- a/src/docs/sphinx/Actions/index.rst +++ b/src/docs/sphinx/Actions/index.rst @@ -16,6 +16,7 @@ Ascent Actions Pipelines Extracts Triggers + Logging Examples ExpressionsOverview expression_objects From 8c6e3ea54927697892b7dac8cf10b45a52996026 Mon Sep 17 00:00:00 2001 From: Emily Howell Date: Thu, 16 Jan 2025 15:54:12 -0800 Subject: [PATCH 6/7] Adding the ability to set the log threshold when the open log action is called --- src/libs/ascent/runtimes/ascent_main_runtime.cpp | 12 +++++++++++- src/tests/ascent/t_ascent_logging.cpp | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libs/ascent/runtimes/ascent_main_runtime.cpp b/src/libs/ascent/runtimes/ascent_main_runtime.cpp index b54f44625..5bf34e0ad 100644 --- a/src/libs/ascent/runtimes/ascent_main_runtime.cpp +++ b/src/libs/ascent/runtimes/ascent_main_runtime.cpp @@ -1941,7 +1941,17 @@ AscentRuntime::BuildGraph(const conduit::Node &actions) { // Open Ascent Logging Stream // This starts logging - ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_DEBUG_ID); + + + if(action.has_path("log_threshold")) + { + ascent::Logger::instance().set_log_threshold(action["log_threshold"].as_string()); + } + else + { + ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_DEBUG_ID); + } + std::string file_pattern = action.has_path("file_pattern") ? action["file_pattern"].as_string() : "ascent_log_output.yaml"; ASCENT_LOG_OPEN(file_pattern); diff --git a/src/tests/ascent/t_ascent_logging.cpp b/src/tests/ascent/t_ascent_logging.cpp index 1dc7b1138..faa035b57 100644 --- a/src/tests/ascent/t_ascent_logging.cpp +++ b/src/tests/ascent/t_ascent_logging.cpp @@ -271,6 +271,7 @@ TEST(ascent_logging, test_logging_actions_threshold) conduit::Node &begin_logs= actions_begin_logs.append(); begin_logs["action"] = "open_log"; begin_logs["file_pattern"] = log_file; + begin_logs["log_threshold"] = "all"; conduit::Node &set_threshold_logs_open= actions_begin_logs.append(); set_threshold_logs_open["action"] = "set_log_threshold"; set_threshold_logs_open["log_threshold"] = "error"; From 08beb6d51325a609048eeb7501171e4130cecd20 Mon Sep 17 00:00:00 2001 From: Emily Howell Date: Thu, 23 Jan 2025 15:20:58 -0800 Subject: [PATCH 7/7] Adding handling for ascent logging actions for MPI and testing --- .../ascent/runtimes/ascent_main_runtime.cpp | 19 +++- src/tests/ascent/t_ascent_logging.cpp | 5 +- .../ascent/t_ascent_mpi_ascent_runtime.cpp | 103 ++++++++++++++++++ 3 files changed, 123 insertions(+), 4 deletions(-) diff --git a/src/libs/ascent/runtimes/ascent_main_runtime.cpp b/src/libs/ascent/runtimes/ascent_main_runtime.cpp index 5bf34e0ad..289f1e052 100644 --- a/src/libs/ascent/runtimes/ascent_main_runtime.cpp +++ b/src/libs/ascent/runtimes/ascent_main_runtime.cpp @@ -1952,9 +1952,24 @@ AscentRuntime::BuildGraph(const conduit::Node &actions) ascent::Logger::instance().set_log_threshold(ascent::Logger::LOG_DEBUG_ID); } - std::string file_pattern = action.has_path("file_pattern") ? + #if defined(ASCENT_MPI_ENABLED) + std::string file_pattern = action.has_path("file_pattern") ? + action["file_pattern"].as_string() : "ascent_log_output_rank_{rank:05d}.yaml"; + + int comm_id = flow::Workspace::default_mpi_comm(); + MPI_Comm mpi_comm = MPI_Comm_f2c(comm_id); + int comm_size = 1; + MPI_Comm_size(mpi_comm, &comm_size); + ASCENT_LOG_OPEN_RANK( file_pattern, m_rank ); + ASCENT_LOG_DEBUG(conduit_fmt::format("mpi info: rank={}, size={}", + m_rank, + comm_size)); + #else + std::string file_pattern = action.has_path("file_pattern") ? action["file_pattern"].as_string() : "ascent_log_output.yaml"; - ASCENT_LOG_OPEN(file_pattern); + ASCENT_LOG_OPEN(file_pattern); + ASCENT_LOG_DEBUG("MPI not enabled"); + #endif } else if(action_name == "flush_log") { diff --git a/src/tests/ascent/t_ascent_logging.cpp b/src/tests/ascent/t_ascent_logging.cpp index faa035b57..f494678e7 100644 --- a/src/tests/ascent/t_ascent_logging.cpp +++ b/src/tests/ascent/t_ascent_logging.cpp @@ -224,9 +224,10 @@ TEST(ascent_logging, test_logging_actions) // check that the log file has the expected number of logs in it (1 open, 3 execution, 1 close) conduit::Node log_file_contents; log_file_contents.load(log_file); - EXPECT_EQ(log_file_contents.number_of_children(), 5); + EXPECT_EQ(log_file_contents.number_of_children(), 6); } +//----------------------------------------------------------------------------- TEST(ascent_logging, test_logging_actions_threshold) { Node n; @@ -307,5 +308,5 @@ TEST(ascent_logging, test_logging_actions_threshold) // check that the log file has the expected number of logs in it (1 open, 3 execution, 1 close) conduit::Node log_file_contents; log_file_contents.load(log_file); - EXPECT_EQ(log_file_contents.number_of_children(), 2); + EXPECT_EQ(log_file_contents.number_of_children(), 3); } diff --git a/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp b/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp index 8232b4b1d..3c9992151 100644 --- a/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp +++ b/src/tests/ascent/t_ascent_mpi_ascent_runtime.cpp @@ -262,6 +262,109 @@ TEST(ascent_mpi_runtime, test_mpi_logs) EXPECT_TRUE(conduit::utils::is_file(log_base + "_c_01.yaml")); } +//----------------------------------------------------------------------------- +TEST(ascent_mpi_runtime, test_logging_actions_mpi) +{ + + 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; + } + + // + // 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); + + // + // 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 = ""; + if(par_rank == 0) + { + output_path = prepare_output_dir(); + } + else + { + output_path = output_dir(); + } + string output_file = conduit::utils::join_file_path(output_path,"tout_logging_render4_"); + string log_base = conduit::utils::join_file_path(output_path,"ascent_action_log_mpi_"); + string log_file = log_base +"{rank:05d}.yaml"; + + // remove old images/log files before rendering + if(par_rank == 0) + { + remove_test_image(output_file); + conduit::utils::remove_path_if_exists(log_base + "00000.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; + + conduit::Node actions_begin_logs; + conduit::Node &begin_logs= actions_begin_logs.append(); + begin_logs["action"] = "open_log"; + begin_logs["file_pattern"] = log_file; + begin_logs["log_threshold"] = "all"; + + conduit::Node actions_flush_logs; + conduit::Node &flush_logs= actions_flush_logs.append(); + flush_logs["action"] = "flush_log"; + + conduit::Node actions_close_logs; + conduit::Node &close_logs= actions_close_logs.append(); + close_logs["action"] = "close_log"; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent_opts["runtime"] = "ascent"; + ascent.open(ascent_opts); + + ascent.publish(data); + ascent.execute(actions_begin_logs); + ascent.execute(actions); + ascent.execute(actions_flush_logs); + ascent.execute(actions_close_logs); + ascent.close(); + + // check that the log file exists + MPI_Barrier(comm); + EXPECT_TRUE(conduit::utils::is_file(log_base + "00000.yaml")); + + // check that the log file has the expected number of logs in it (1 open, 3 execution, 1 close) + conduit::Node log_file_contents; + log_file_contents.load(log_base + "00000.yaml"); + EXPECT_EQ(log_file_contents.number_of_children(), 6); +} + //----------------------------------------------------------------------------- int main(int argc, char* argv[])