Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:48

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2020-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file corecel/io/Logger.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <string>
0011 #include <utility>
0012 
0013 #include "LoggerTypes.hh"
0014 
0015 #include "detail/LoggerMessage.hh"  // IWYU pragma: export
0016 
0017 //---------------------------------------------------------------------------//
0018 // MACROS
0019 //---------------------------------------------------------------------------//
0020 //! Inject the source code provenance (current file and line)
0021 #define CELER_CODE_PROVENANCE  \
0022     ::celeritas::LogProvenance \
0023     {                          \
0024         __FILE__, __LINE__     \
0025     }
0026 
0027 /*!
0028  * \def CELER_LOG
0029  *
0030  * Return a LogMessage object for streaming into at the given level. The
0031  * regular \c CELER_LOG call is for code paths that happen uniformly in
0032  * parallel.
0033  *
0034  * The logger will only format and print messages. It is not responsible
0035  * for cleaning up the state or exiting an app.
0036  *
0037  * \code
0038  CELER_LOG(debug) << "Don't print this in general";
0039  CELER_LOG(warning) << "You may want to reconsider your life choices";
0040  CELER_LOG(critical) << "Caught a fatal exception: " << e.what();
0041  * \endcode
0042  */
0043 #define CELER_LOG(LEVEL)                               \
0044     ::celeritas::world_logger()(CELER_CODE_PROVENANCE, \
0045                                 ::celeritas::LogLevel::LEVEL)
0046 
0047 //---------------------------------------------------------------------------//
0048 /*!
0049  * \def CELER_LOG_LOCAL
0050  *
0051  * Like \c CELER_LOG but for code paths that may only happen on a single
0052  * process. Use sparingly.
0053  */
0054 #define CELER_LOG_LOCAL(LEVEL)                        \
0055     ::celeritas::self_logger()(CELER_CODE_PROVENANCE, \
0056                                ::celeritas::LogLevel::LEVEL)
0057 
0058 namespace celeritas
0059 {
0060 class MpiCommunicator;
0061 
0062 //---------------------------------------------------------------------------//
0063 /*!
0064  * Manage logging in serial and parallel.
0065  *
0066  * This should generally be called by the \c world_logger and \c
0067  * self_logger functions below. The call \c operator() returns an object that
0068  * should be streamed into in order to create a log message.
0069  *
0070  * This object \em is assignable, so to replace the default log handler with a
0071  * different one, you can call \code
0072    world_logger = Logger(celeritas::comm_world(), my_handler);
0073  * \endcode
0074  */
0075 class Logger
0076 {
0077   public:
0078     //!@{
0079     //! \name Type aliases
0080     using Message = detail::LoggerMessage;
0081     //!@}
0082 
0083   public:
0084     //! Get the default log level
0085     static constexpr LogLevel default_level() { return LogLevel::status; }
0086 
0087     // Construct with default celeritas communicator
0088     explicit Logger(LogHandler handle);
0089 
0090     // Construct with custom communicator (only rank zero is active) and
0091     // handler
0092     Logger(MpiCommunicator const& comm, LogHandler handle);
0093 
0094     // Create a logger that flushes its contents when it destructs
0095     inline Message operator()(LogProvenance&& prov, LogLevel lev);
0096 
0097     //! Set the minimum logging verbosity
0098     void level(LogLevel lev) { min_level_ = lev; }
0099 
0100     //! Get the current logging verbosity
0101     LogLevel level() const { return min_level_; }
0102 
0103   private:
0104     LogHandler handle_;
0105     LogLevel min_level_{default_level()};
0106 };
0107 
0108 //---------------------------------------------------------------------------//
0109 // INLINE DEFINITIONS
0110 //---------------------------------------------------------------------------//
0111 /*!
0112  * Create a logger that flushes its contents when it destructs.
0113  *
0114  * It's assumed that log messages will be relatively unlikely (and expensive
0115  * anyway), so we mark as \c CELER_UNLIKELY to optimize for the no-logging
0116  * case.
0117  */
0118 auto Logger::operator()(LogProvenance&& prov, LogLevel lev) -> Message
0119 {
0120     LogHandler* handle = nullptr;
0121     if (CELER_UNLIKELY(handle_ && lev >= min_level_))
0122     {
0123         handle = &handle_;
0124     }
0125     return {handle, std::move(prov), lev};
0126 }
0127 
0128 //---------------------------------------------------------------------------//
0129 // FREE FUNCTIONS
0130 //---------------------------------------------------------------------------//
0131 // Get the log level from an environment variable
0132 LogLevel log_level_from_env(std::string const&);
0133 
0134 // Create loggers with reasonable default behaviors.
0135 Logger make_default_world_logger();
0136 Logger make_default_self_logger();
0137 
0138 // Parallel logger (print only on "main" process)
0139 Logger& world_logger();
0140 
0141 // Serial logger (print on *every* process)
0142 Logger& self_logger();
0143 
0144 //---------------------------------------------------------------------------//
0145 }  // namespace celeritas