Loading...
Searching...
No Matches
logging.h
Go to the documentation of this file.
// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: MPL-2.0
#ifndef OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
#define OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
#include <openvdb/version.h>
#ifdef OPENVDB_USE_LOG4CPLUS
#include <log4cplus/appender.h>
#include <log4cplus/configurator.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/layout.h>
#include <log4cplus/logger.h>
#include <log4cplus/spi/loggingevent.h>
#include <algorithm> // for std::remove()
#include <cstring> // for ::strrchr()
#include <memory>
#include <sstream>
#include <string>
#include <vector>
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace logging {
/// @brief Message severity level
enum class Level {
Debug = log4cplus::DEBUG_LOG_LEVEL,
Info = log4cplus::INFO_LOG_LEVEL,
Warn = log4cplus::WARN_LOG_LEVEL,
Error = log4cplus::ERROR_LOG_LEVEL,
Fatal = log4cplus::FATAL_LOG_LEVEL
};
/// @cond OPENVDB_DOCS_INTERNAL
namespace internal {
/// @brief log4cplus layout that outputs text in different colors
/// for different log levels, using ANSI escape codes
class ColoredPatternLayout: public log4cplus::PatternLayout
{
public:
explicit ColoredPatternLayout(const std::string& progName_, bool useColor = true)
: log4cplus::PatternLayout(
progName_.empty() ? std::string{"%5p: %m%n"} : (progName_ + " %5p: %m%n"))
, mUseColor(useColor)
, mProgName(progName_)
{
}
~ColoredPatternLayout() override {}
const std::string& progName() const { return mProgName; }
void formatAndAppend(log4cplus::tostream& strm,
const log4cplus::spi::InternalLoggingEvent& event) override
{
if (!mUseColor) {
log4cplus::PatternLayout::formatAndAppend(strm, event);
return;
}
log4cplus::tostringstream s;
switch (event.getLogLevel()) {
case log4cplus::DEBUG_LOG_LEVEL: s << "\033[32m"; break; // green
case log4cplus::ERROR_LOG_LEVEL:
case log4cplus::FATAL_LOG_LEVEL: s << "\033[31m"; break; // red
case log4cplus::INFO_LOG_LEVEL: s << "\033[36m"; break; // cyan
case log4cplus::WARN_LOG_LEVEL: s << "\033[35m"; break; // magenta
}
log4cplus::PatternLayout::formatAndAppend(s, event);
strm << s.str() << "\033[0m" << std::flush;
}
// Disable deprecation warnings for std::auto_ptr.
#if defined(__ICC)
#pragma warning push
#pragma warning disable:1478
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#if defined(LOG4CPLUS_VERSION) && defined(LOG4CPLUS_MAKE_VERSION)
#if LOG4CPLUS_VERSION >= LOG4CPLUS_MAKE_VERSION(2, 0, 0)
// In log4cplus 2.0.0, std::auto_ptr was replaced with std::unique_ptr.
using Ptr = std::unique_ptr<log4cplus::Layout>;
#else
using Ptr = std::auto_ptr<log4cplus::Layout>;
#endif
#else
using Ptr = std::auto_ptr<log4cplus::Layout>;
#endif
static Ptr create(const std::string& progName_, bool useColor = true)
{
return Ptr{new ColoredPatternLayout{progName_, useColor}};
}
#if defined(__ICC)
#pragma warning pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
private:
bool mUseColor = true;
std::string mProgName;
}; // class ColoredPatternLayout
inline log4cplus::Logger
getLogger()
{
return log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("openvdb"));
}
inline log4cplus::SharedAppenderPtr
getAppender()
{
return getLogger().getAppender(LOG4CPLUS_TEXT("OPENVDB"));
}
} // namespace internal
/// @endcond
/// @brief Return the current logging level.
inline Level
getLevel()
{
switch (internal::getLogger().getLogLevel()) {
case log4cplus::DEBUG_LOG_LEVEL: return Level::Debug;
case log4cplus::INFO_LOG_LEVEL: return Level::Info;
case log4cplus::WARN_LOG_LEVEL: return Level::Warn;
case log4cplus::ERROR_LOG_LEVEL: return Level::Error;
case log4cplus::FATAL_LOG_LEVEL: break;
}
return Level::Fatal;
}
/// @brief Set the logging level. (Lower-level messages will be suppressed.)
inline void
setLevel(Level lvl)
{
internal::getLogger().setLogLevel(static_cast<log4cplus::LogLevel>(lvl));
}
/// @brief If "-debug", "-info", "-warn", "-error" or "-fatal" is found
/// in the given array of command-line arguments, set the logging level
/// appropriately and remove the relevant argument(s) from the array.
inline void
setLevel(int& argc, char* argv[])
{
for (int i = 1; i < argc; ++i) { // note: skip argv[0]
const std::string arg{argv[i]};
bool remove = true;
if (arg == "-debug") { setLevel(Level::Debug); }
else if (arg == "-error") { setLevel(Level::Error); }
else if (arg == "-fatal") { setLevel(Level::Fatal); }
else if (arg == "-info") { setLevel(Level::Info); }
else if (arg == "-warn") { setLevel(Level::Warn); }
else { remove = false; }
if (remove) argv[i] = nullptr;
}
auto end = std::remove(argv + 1, argv + argc, nullptr);
argc = static_cast<int>(end - argv);
}
/// @brief Specify a program name to be displayed in log messages.
inline void
setProgramName(const std::string& progName, bool useColor = true)
{
// Change the layout of the OpenVDB appender to use colored text
// and to incorporate the supplied program name.
if (auto appender = internal::getAppender()) {
appender->setLayout(internal::ColoredPatternLayout::create(progName, useColor));
}
}
/// @brief Initialize the logging system if it is not already initialized.
inline void
initialize(bool useColor = true)
{
log4cplus::initialize();
if (internal::getAppender()) return; // already initialized
// Create the OpenVDB logger if it doesn't already exist.
auto logger = internal::getLogger();
// Disable "additivity", so that OpenVDB-related messages are directed
// to the OpenVDB logger only and are not forwarded up the logger tree.
logger.setAdditivity(false);
// Attach a console appender to the OpenVDB logger.
if (auto appender = log4cplus::SharedAppenderPtr{new log4cplus::ConsoleAppender}) {
appender->setName(LOG4CPLUS_TEXT("OPENVDB"));
logger.addAppender(appender);
}
setLevel(Level::Warn);
setProgramName("", useColor);
}
/// @brief Initialize the logging system from command-line arguments.
/// @details If "-debug", "-info", "-warn", "-error" or "-fatal" is found
/// in the given array of command-line arguments, set the logging level
/// appropriately and remove the relevant argument(s) from the array.
inline void
initialize(int& argc, char* argv[], bool useColor = true)
{
initialize();
setLevel(argc, argv);
auto progName = (argc > 0 ? argv[0] : "");
if (const char* ptr = ::strrchr(progName, '/')) progName = ptr + 1;
setProgramName(progName, useColor);
}
} // namespace logging
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#define OPENVDB_LOG(level, message) \
do { \
auto _log = openvdb::logging::internal::getLogger(); \
if (_log.isEnabledFor(log4cplus::level##_LOG_LEVEL)) { \
std::ostringstream _buf; \
_buf << message; \
_log.forcedLog(log4cplus::level##_LOG_LEVEL, _buf.str(), __FILE__, __LINE__); \
} \
} while (0);
/// Log an info message of the form '<TT>someVar << "some text" << ...</TT>'.
#define OPENVDB_LOG_INFO(message) OPENVDB_LOG(INFO, message)
/// Log a warning message of the form '<TT>someVar << "some text" << ...</TT>'.
#define OPENVDB_LOG_WARN(message) OPENVDB_LOG(WARN, message)
/// Log an error message of the form '<TT>someVar << "some text" << ...</TT>'.
#define OPENVDB_LOG_ERROR(message) OPENVDB_LOG(ERROR, message)
/// Log a fatal error message of the form '<TT>someVar << "some text" << ...</TT>'.
#define OPENVDB_LOG_FATAL(message) OPENVDB_LOG(FATAL, message)
#ifdef DEBUG
/// In debug builds only, log a debugging message of the form '<TT>someVar << "text" << ...</TT>'.
#define OPENVDB_LOG_DEBUG(message) OPENVDB_LOG(DEBUG, message)
#else
/// In debug builds only, log a debugging message of the form '<TT>someVar << "text" << ...</TT>'.
#define OPENVDB_LOG_DEBUG(message)
#endif
/// @brief Log a debugging message in both debug and optimized builds.
/// @warning Don't use this in performance-critical code.
#define OPENVDB_LOG_DEBUG_RUNTIME(message) OPENVDB_LOG(DEBUG, message)
#else // ifdef OPENVDB_USE_LOG4CPLUS
#include <iostream>
#define OPENVDB_LOG_INFO(mesg)
#define OPENVDB_LOG_WARN(mesg) do { std::cerr << "WARNING: " << mesg << std::endl; } while (0);
#define OPENVDB_LOG_ERROR(mesg) do { std::cerr << "ERROR: " << mesg << std::endl; } while (0);
#define OPENVDB_LOG_FATAL(mesg) do { std::cerr << "FATAL: " << mesg << std::endl; } while (0);
#define OPENVDB_LOG_DEBUG(mesg)
#define OPENVDB_LOG_DEBUG_RUNTIME(mesg)
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace logging {
enum class Level { Debug, Info, Warn, Error, Fatal };
inline Level getLevel() { return Level::Warn; }
inline void setLevel(Level) {}
inline void setLevel(int&, char*[]) {}
inline void setProgramName(const std::string&, bool = true) {}
inline void initialize() {}
inline void initialize(int&, char*[], bool = true) {}
} // namespace logging
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif // OPENVDB_USE_LOG4CPLUS
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace logging {
/// @brief A LevelScope object sets the logging level to a given level
/// and restores it to the current level when the object goes out of scope.
struct LevelScope
{
Level level;
explicit LevelScope(Level newLevel): level(getLevel()) { setLevel(newLevel); }
~LevelScope() { setLevel(level); }
};
} // namespace logging
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif // OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
openvdb::v10_0::internal
Definition openvdb.h:114
openvdb::v10_0::logging
Definition logging.h:28
openvdb::v10_0::logging::Level
Level
Message severity level.
Definition logging.h:31
openvdb::v10_0::logging::Level::Info
@ Info
Definition logging.h:33
openvdb::v10_0::logging::Level::Warn
@ Warn
Definition logging.h:34
openvdb::v10_0::logging::Level::Fatal
@ Fatal
Definition logging.h:36
openvdb::v10_0::logging::Level::Error
@ Error
Definition logging.h:35
openvdb::v10_0::logging::Level::Debug
@ Debug
Definition logging.h:32
openvdb::v10_0::logging::setProgramName
void setProgramName(const std::string &progName, bool useColor=true)
Specify a program name to be displayed in log messages.
Definition logging.h:186
openvdb::v10_0::logging::initialize
void initialize(bool useColor=true)
Initialize the logging system if it is not already initialized.
Definition logging.h:198
openvdb::v10_0::logging::getLevel
Level getLevel()
Return the current logging level.
Definition logging.h:141
openvdb::v10_0::logging::setLevel
void setLevel(Level lvl)
Set the logging level. (Lower-level messages will be suppressed.).
Definition logging.h:156
openvdb
Definition Exceptions.h:13
openvdb::v10_0::logging::LevelScope::level
Level level
Definition logging.h:313
openvdb::v10_0::logging::LevelScope::LevelScope
LevelScope(Level newLevel)
Definition logging.h:314
openvdb::v10_0::logging::LevelScope::~LevelScope
~LevelScope()
Definition logging.h:315
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212