Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLIC: Rank count and list formatting #1420

Open
gberg617 opened this issue Sep 23, 2024 · 5 comments
Open

SLIC: Rank count and list formatting #1420

gberg617 opened this issue Sep 23, 2024 · 5 comments
Labels
Reviewed Slic Issues related to Axom's 'slic' component User Request Issues related to user requests

Comments

@gberg617
Copy link

gberg617 commented Sep 23, 2024

I'm trying to write to a log file using both GenericOutputStream (for messages from the root rank), and LumberjackStream (for messages from another rank that might need to be filtered). Traditionally, the formatting of this log file would look something like this:

[INFO ][2024/09/20 18:18:57][ 0][ 0][0.000000e+00] Message from root rank
[INFO ][2024/09/20 18:18:57][ 2][ 0][2.200000e-02] Message from rank 2

The number in the third pair of square brackets above indicates the rank that creates the message. Messages that are filtered typically print only the first rank.

There are two issues I'm encountering trying to format this:

  1. GenericOutputStream does not have a rank associated with it. The formatting of the <RANK> keyword will just be empty. For all of my applications, I prefer the rank to always print "0", and rank count to be "1" so that it has consistent formatting. Is there a way to override this formatting? Or would you recommend that I create my own stream class to do this?
  2. Lumberjack streams now have the trailing dots "..." for the rank list, even if the rank count is 1. Is it possible at all to disable the dots so that I just get the first number in the rank list? This would also help with consistency in formatting.

Any guidance on this would be greatly appreciated!

@gberg617 gberg617 added Slic Issues related to Axom's 'slic' component User Request Issues related to user requests labels Sep 23, 2024
@gberg617
Copy link
Author

@white238 @bmhan12

@bmhan12
Copy link
Contributor

bmhan12 commented Sep 23, 2024

GenericOutputStream does not have a rank associated with it. The formatting of the keyword will just be empty. For all of my applications, I prefer the rank to always print "0", and rank count to be "1" so that it has consistent formatting. Is there a way to override this formatting? Or would you recommend that I create my own stream class to do this?

GenericOutputStream is for non-MPI use cases and builds without MPI, so there is not a way to get the rank information (the "" parameters):

(*m_stream) << this->getFormatedMessage(message::getLevelAsString(msgLevel),
message,
tagName,
"",
"",
fileName,
line);

You should use SynchronizedStream for unfiltered MPI messages. The rank count will always be 1 (no filtering done), and assuming the message is always from root, the rank should be 0:

m_cache->messages.push_back(
this->getFormatedMessage(message::getLevelAsString(msgLevel),
message,
tagName,
std::to_string(rank),
"1",
fileName,
line));



Lumberjack streams now have the trailing dots "..." for the rank list, even if the rank count is 1. Is it possible at all to disable the dots so that I just get the first number in the rank list? This would also help with consistency in formatting.

I'm not too sure where this is coming from. @white238, could it be this line here in Lumberjack (line 58)?

std::string Message::stringOfRanks(std::string delimiter) const
{
std::string returnString = "";
int ranksSize = m_ranks.size();
for(int i = 0; i < ranksSize; ++i)
{
returnString += std::to_string(m_ranks[i]);
if(i < (ranksSize - 1))
{
returnString += delimiter;
}
}
// Indicate we might have more ranks we aren't individually tracking
if(m_ranksLimitReached)
{
returnString += "...";
}
return returnString;
}

@gberg617
Copy link
Author

I had tried the SynchronizedStream previously, the formatting for this worked well. From a conceptual standpoint, I wasn't sure if using this makes sense if it is only used to output messages from a single rank (the root rank). I noticed that the flush method for SynchronizedStream has some MPI logic to check for messages that need to be sent or received. Would these be called when I'm just expecting a single rank to output messages? If so, would there be any performance implications for calling these MPI routines?

@bmhan12
Copy link
Contributor

bmhan12 commented Sep 23, 2024

I had tried the SynchronizedStream previously, the formatting for this worked well. From a conceptual standpoint, I wasn't sure if using this makes sense if it is only used to output messages from a single rank (the root rank). I noticed that the flush method for SynchronizedStream has some MPI logic to check for messages that need to be sent or received. Would these be called when I'm just expecting a single rank to output messages? If so, would there be any performance implications for calling these MPI routines?

I see, that's a good point. You likely would see some costs for those MPI routines.

Alternatively, if you know for sure the GenericOutputStream will be used only for the root node, you could use a constructor with the format parameter to hardcode the rank/rank count information.

For example, in this Lumberjack format string example:

// Initialize SLIC
constexpr const char* format = R"(
<MESSAGE>
\t<TIMESTAMP>
\tLEVEL=<LEVEL>
\tRANKS=<RANK>
\tRANK_COUNT=<RANK_COUNT>
\tFILE=<FILE>
\tLINE=<LINE>
)";
slic::initialize();
// Set SLIC logging level and Lumberjack Logging stream
slic::setLoggingMsgLevel(slic::message::Debug);
slic::disableAbortOnError();
slic::LumberjackStream* ljStream =
new slic::LumberjackStream(&std::cout, MPI_COMM_WORLD, RANKSLIMIT, format);
slic::addStreamToAllMsgLevels(ljStream);

You can instead hardcode the rank and rank count:

  // Initialize SLIC
  constexpr const char* format = R"(
<MESSAGE>
\t<TIMESTAMP>
\tLEVEL=<LEVEL>
\tRANKS=0
\tRANK_COUNT=1
\tFILE=<FILE>
\tLINE=<LINE>
)";

EDIT: Essentially, you can use these constructors with the format parameter to customize your GenericOutputStream to include your rank information:

/*!
* \brief Constructs a GenericOutputStream instance with the given stream and
* message formatting.
* \param [in] os pointer to a user-supplied ostream instance.
* \param [in] format the format string.
* \pre os != NULL
* \see LogStream::setFormatString for the format string.
*/
GenericOutputStream(std::ostream* os, const std::string& format);
/*!
* \brief Constructs a GenericOutputStream instance specified by the given
* string and message formatting.
* The string input determines the stream as follows:
* - "cout" makes std::cout the output stream
* - "cerr" makes std::cerr the output stream
* - Any other input will construct a std::ofstream associated with input
* \param [in] stream the string to control type of stream created
* \param [in] format the format string.
* \see LogStream::setFormatString for the format string.
*
* \note This constructor avoids creating an empty file if this
* GenericOutputStream never flushes a message.
*/
GenericOutputStream(const std::string& stream, const std::string& format);

@gberg617
Copy link
Author

gberg617 commented Sep 23, 2024

This is an interesting point. The only formatting keyword I generally pass to Slic is <MESSAGE> because I find it easier to format the full message in the application code itself. This also makes it easier to embed certain variables within the message that don't have Slic keywords associated with them such as simulation time and simulation cycle. As a bit of a side note, this comes at a cost of having to send longer messages when using the Lumberjack stream (since it includes all the formatting), but I don't really know how else to get around this issue.

Perhaps to enforce rank=0, I can check which stream is used when I format my messages and override the <RANK> keyword for the string 0. This could be a viable alternative. UPDATE: This does work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Reviewed Slic Issues related to Axom's 'slic' component User Request Issues related to user requests
Projects
None yet
Development

No branches or pull requests

3 participants