Optionally use std::format in LOG4CXX_XXXX_FMT macros instead of fmt::format (#291)
* Optionally use std::format in LOG4CXX_XXXXX_FMT macros instead of fmt::format
* Improve LOG4CXX_XXXX_FMT macro documentation by adding examples
* Allow LOG4CXX_FORMAT_NS=fmt preprocessor directive with a library built with LOG4CXX_FORMAT_NS=std
* Document cmake and preprocessor macros
* Include format implementation in the log4cxx configuration summary
* Prevent gcc compiler complaining about a comma before an empty __VA_ARGS__
---------
Co-authored-by: Stephen Webb <swebb2066@gmail.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b3670c..c2cd2c0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -309,8 +309,9 @@
message(STATUS "C++ version and Boost settings:")
message(STATUS " Prefer boost: ................... : ${PREFER_BOOST}")
message(STATUS " make_unique implementation :..... : ${STD_MAKE_UNIQUE_IMPL}")
-message(STATUS " thread_local support? ........... : ${HAS_THREAD_LOCAL}")
message(STATUS " filesystem implementation ....... : ${FILESYSTEM_IMPL}")
+message(STATUS " format implementation ........... : ${LOG4CXX_FORMAT_NAMESPACE}::format")
+message(STATUS " thread_local support? ........... : ${HAS_THREAD_LOCAL}")
if(BUILD_TESTING)
message(STATUS "Applications required for tests:")
diff --git a/src/examples/cpp/format-string.cpp b/src/examples/cpp/format-string.cpp
index 19dafa3..10053ff 100644
--- a/src/examples/cpp/format-string.cpp
+++ b/src/examples/cpp/format-string.cpp
@@ -18,9 +18,13 @@
#include <stdlib.h>
#include <log4cxx/basicconfigurator.h>
#include <locale.h>
+#if LOG4CXX_USING_STD_FORMAT
+#include <format>
+#else
#include <fmt/core.h>
#include <fmt/color.h>
#include <fmt/ostream.h>
+#endif
#include <iomanip>
using namespace log4cxx;
@@ -34,7 +38,22 @@
stream << "[MyStruct x:" << mystruct.x << "]";
return stream;
}
-#if FMT_VERSION >= (9 * 10000)
+
+#if LOG4CXX_USING_STD_FORMAT
+template <typename Char>
+struct basic_ostream_formatter
+ : std::formatter<std::basic_string_view<Char>, Char>
+{
+ template <typename T, typename OutputIt>
+ auto format(const T& value, std::basic_format_context<OutputIt, Char>& ctx) const -> OutputIt
+ {
+ std::basic_stringstream<Char> ss;
+ ss << value;
+ return std::formatter<std::basic_string_view<Char>, Char>::format(ss.view(), ctx);
+ }
+};
+template <> struct std::formatter<MyStruct> : basic_ostream_formatter<char> {};
+#elif FMT_VERSION >= (9 * 10000)
template <> struct fmt::formatter<MyStruct> : ostream_formatter {};
#endif
@@ -46,10 +65,12 @@
LoggerPtr rootLogger = Logger::getRootLogger();
LOG4CXX_INFO_FMT( rootLogger, "This is a {} mesage", "test" );
+#if !LOG4CXX_USING_STD_FORMAT
LOG4CXX_INFO_FMT( rootLogger, fmt::fg(fmt::color::red), "Messages can be colored" );
+#endif
LOG4CXX_INFO_FMT( rootLogger, "We can also align text to the {:<10} or {:>10}", "left", "right" );
- MyStruct mine;
+ MyStruct mine{ 42 };
LOG4CXX_INFO_FMT( rootLogger, "This custom type {} can also be logged, since it implements operator<<", mine );
LOG4CXX_INFO( rootLogger, "Numbers can be formatted with excessive operator<<: "
diff --git a/src/main/include/CMakeLists.txt b/src/main/include/CMakeLists.txt
index 3127a21..4e0603d 100644
--- a/src/main/include/CMakeLists.txt
+++ b/src/main/include/CMakeLists.txt
@@ -96,6 +96,13 @@
set(LOG4CXX_DECLARE_DEFAULT_NS_ALIAS 1)
endif()
+set(LOG4CXX_FORMAT_NAMESPACE "fmt" CACHE STRING "format() function namespace, choice of fmt (default), std")
+set_property(CACHE LOG4CXX_FORMAT_NAMESPACE PROPERTY STRINGS "fmt" "std")
+set(LOG4CXX_USE_STANDARD_FORMAT 0)
+if("std" STREQUAL "${LOG4CXX_FORMAT_NAMESPACE}")
+ set(LOG4CXX_USE_STANDARD_FORMAT 1)
+endif()
+
# Configure log4cxx_private.h
set(LOG4CXX_CHARSET "utf-8" CACHE STRING "LogString characters, choice of utf-8 (default), ISO-8859-1, US-ASCII, EBCDIC, locale")
set_property(CACHE LOG4CXX_CHARSET PROPERTY STRINGS "utf-8" "ISO-8859-1" "US-ASCII" "EBCDIC" "locale")
diff --git a/src/main/include/log4cxx/log4cxx.h.in b/src/main/include/log4cxx/log4cxx.h.in
index b16d3de..530bc82 100644
--- a/src/main/include/log4cxx/log4cxx.h.in
+++ b/src/main/include/log4cxx/log4cxx.h.in
@@ -123,4 +123,11 @@
namespace log4cxx = LOG4CXX_NS;
#endif
+#define LOG4CXX_USING_STD_FORMAT @LOG4CXX_USE_STANDARD_FORMAT@
+#if !defined(LOG4CXX_FORMAT_NS) && LOG4CXX_USING_STD_FORMAT
+#define LOG4CXX_FORMAT_NS std
+#elif !defined(LOG4CXX_FORMAT_NS)
+#define LOG4CXX_FORMAT_NS fmt
+#endif
+
#endif
diff --git a/src/main/include/log4cxx/logger.h b/src/main/include/log4cxx/logger.h
index b0f573d..403e7c0 100644
--- a/src/main/include/log4cxx/logger.h
+++ b/src/main/include/log4cxx/logger.h
@@ -2029,15 +2029,16 @@
logger->addEvent(level, oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-Add a new logging event containing libfmt formatted <code>...</code> to attached appender(s) if this logger is enabled for \c events.
+Add a new logging event containing a message defined by \c fmt and <code>...</code> to attached appender(s) if this logger is enabled for \c events.
@param logger the logger to be used.
@param level The logging event level.
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
*/
-#define LOG4CXX_LOG_FMT(logger, level, ...) do { \
+#define LOG4CXX_LOG_FMT(logger, level, fmt, ...) do { \
if (logger->isEnabledFor(level)) {\
- logger->addEvent(level, fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(level, ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
/**
Add a new logging event containing \c message to attached appender(s) if this logger is enabled for \c events.
@@ -2058,7 +2059,6 @@
@param logger the logger that has the enabled status.
@param message a valid r-value expression of an <code>operator<<(std::ostream&. ...)</code> overload.
-<p>Example:
~~~{.cpp}
LOG4CXX_DEBUG(m_log, "AddMesh:"
<< " name " << meshName
@@ -2076,17 +2076,18 @@
logger->addEvent(::LOG4CXX_NS::Level::getDebug(), oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-Add a new logging event containing libfmt formatted <code>...</code> to attached appender(s) if \c logger is enabled for <code>DEBUG</code> events.
+Add a new logging event containing a message defined by \c fmt and <code>...</code> to attached appender(s) if \c logger is enabled for <code>DEBUG</code> events.
@param logger the logger to be used.
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
*/
-#define LOG4CXX_DEBUG_FMT(logger, ...) do { \
+#define LOG4CXX_DEBUG_FMT(logger, fmt, ...) do { \
if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isDebugEnabledFor(logger))) {\
- logger->addEvent(::LOG4CXX_NS::Level::getDebug(), fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(::LOG4CXX_NS::Level::getDebug(), ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
#else
#define LOG4CXX_DEBUG(logger, message)
-#define LOG4CXX_DEBUG_FMT(logger, ...)
+#define LOG4CXX_DEBUG_FMT(logger, fmt, ...)
#endif
#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 5000
@@ -2096,11 +2097,9 @@
@param logger the logger that has the enabled status.
@param message a valid r-value expression of an <code>operator<<(std::ostream&. ...)</code> overload.
-<p>Example:
~~~{.cpp}
- LOG4CXX_TRACE(m_log, "AddVertex:" << " p " << p[j] << " n " << n << ' ' << color);
+ LOG4CXX_TRACE(m_log, "AddVertex:" << " at " << p << " n " << n << ' ' << color);
~~~
-
*/
#define LOG4CXX_TRACE(logger, message) do { \
if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isTraceEnabledFor(logger))) {\
@@ -2108,17 +2107,22 @@
logger->addEvent(::LOG4CXX_NS::Level::getTrace(), oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-Add a new logging event containing libfmt formatted <code>...</code> to attached appender(s) if \c logger is enabled for <code>TRACE</code> events.
+Add a new logging event containing a message defined by \c fmt and <code>...</code> to attached appender(s) if \c logger is enabled for <code>TRACE</code> events.
@param logger the logger to be used.
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
+
+~~~{.cpp}
+ LOG4CXX_TRACE_FMT(m_log, "AddVertex: at {} n {} {}", p, n, color);
+~~~
*/
-#define LOG4CXX_TRACE_FMT(logger, ...) do { \
+#define LOG4CXX_TRACE_FMT(logger, fmt, ...) do { \
if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isTraceEnabledFor(logger))) {\
- logger->addEvent(::LOG4CXX_NS::Level::getTrace(), fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(::LOG4CXX_NS::Level::getTrace(), ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
#else
#define LOG4CXX_TRACE(logger, message)
-#define LOG4CXX_TRACE_FMT(logger, ...)
+#define LOG4CXX_TRACE_FMT(logger, fmt, ...)
#endif
#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 20000
@@ -2128,7 +2132,6 @@
@param logger the logger that has the enabled status.
@param message a valid r-value expression of an <code>operator<<(std::ostream&. ...)</code> overload.
-<p>Example:
~~~{.cpp}
LOG4CXX_INFO(m_log, surface->GetName()
<< " successfully planned " << std::fixed << std::setprecision(1) << ((plannedArea / (plannedArea + unplannedArea)) * 100.0) << "%"
@@ -2144,17 +2147,26 @@
logger->addEvent(::LOG4CXX_NS::Level::getInfo(), oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-Add a new logging event containing libfmt formatted <code>...</code> to attached appender(s) if \c logger is enabled for <code>INFO</code> events.
+Add a new logging event containing a message defined by \c fmt and <code>...</code> to attached appender(s) if \c logger is enabled for <code>INFO</code> events.
@param logger the logger to be used.
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
+
+~~~{.cpp}
+LOG4CXX_INFO_FMT(m_log, "{} successfully planned {:.1f}% planned area {:.4f}m^2 unplanned area {:.4f}m^2 planned segments {:d} of {:d}"
+ , surface->GetName(), (plannedArea / (plannedArea + unplannedArea)) * 100.0
+ , plannedArea, unplannedArea
+ , surface->GetSegmentPlanCount(), surface->GetSegmentCount()
+ );
+~~~
*/
-#define LOG4CXX_INFO_FMT(logger, ...) do { \
+#define LOG4CXX_INFO_FMT(logger, fmt, ...) do { \
if (::LOG4CXX_NS::Logger::isInfoEnabledFor(logger)) {\
- logger->addEvent(::LOG4CXX_NS::Level::getInfo(), fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(::LOG4CXX_NS::Level::getInfo(), ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
#else
#define LOG4CXX_INFO(logger, message)
-#define LOG4CXX_INFO_FMT(logger, ...)
+#define LOG4CXX_INFO_FMT(logger, fmt, ...)
#endif
#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 30000
@@ -2164,7 +2176,6 @@
@param logger the logger to be used.
@param message a valid r-value expression of an <code>operator<<(std::ostream&. ...)</code> overload.
-<p>Example:
~~~{.cpp}
catch (const std::exception& ex)
{
@@ -2178,17 +2189,25 @@
logger->addEvent(::LOG4CXX_NS::Level::getWarn(), oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-Add a new logging event containing libfmt formatted <code>...</code> to attached appender(s) if \c logger is enabled for <code>WARN</code> events.
+Add a new logging event containing a message defined by \c fmt and <code>...</code> to attached appender(s) if \c logger is enabled for <code>WARN</code> events.
@param logger the logger to be used.
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
+
+~~~{.cpp}
+catch (const std::exception& ex)
+{
+ LOG4CXX_WARN_FMT(m_log, "{}: in {}", ex.what(), m_task->GetParamFilePath());
+}
+~~~
*/
-#define LOG4CXX_WARN_FMT(logger, ...) do { \
+#define LOG4CXX_WARN_FMT(logger, fmt, ...) do { \
if (::LOG4CXX_NS::Logger::isWarnEnabledFor(logger)) {\
- logger->addEvent(::LOG4CXX_NS::Level::getWarn(), fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(::LOG4CXX_NS::Level::getWarn(), ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
#else
#define LOG4CXX_WARN(logger, message)
-#define LOG4CXX_WARN_FMT(logger, ...)
+#define LOG4CXX_WARN_FMT(logger, fmt, ...)
#endif
#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 40000
@@ -2198,7 +2217,6 @@
@param logger the logger to be used.
@param message a valid r-value expression of an <code>operator<<(std::ostream&. ...)</code> overload.
-<p>Example:
~~~{.cpp}
catch (std::exception& ex)
{
@@ -2212,14 +2230,22 @@
logger->addEvent(::LOG4CXX_NS::Level::getError(), oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-Add a new logging event containing libfmt formatted <code>...</code> to attached appender(s) if \c logger is enabled for <code>ERROR</code> events.
+Add a new logging event containing a message defined by \c fmt and <code>...</code> to attached appender(s) if \c logger is enabled for <code>ERROR</code> events.
@param logger the logger to be used.
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
+
+~~~{.cpp}
+catch (std::exception& ex)
+{
+ LOG4CXX_ERROR_FMT(m_log, "{} in AddScanData", ex.what());
+}
+~~~
*/
-#define LOG4CXX_ERROR_FMT(logger, ...) do { \
+#define LOG4CXX_ERROR_FMT(logger, fmt, ...) do { \
if (::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
- logger->addEvent(::LOG4CXX_NS::Level::getError(), fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(::LOG4CXX_NS::Level::getError(), ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
/**
If \c condition is not true, add a new logging event containing \c message to attached appender(s) if \c logger is enabled for <code>ERROR</code> events.
@@ -2235,22 +2261,25 @@
logger->addEvent(::LOG4CXX_NS::Level::getError(), oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-If \c condition is not true, add a new logging event containing libfmt formatted \c message to attached appender(s) if \c logger is enabled for <code>ERROR</code> events.
+If \c condition is not true, add a new logging event containing
+a message defined by \c fmt and <code>...</code> to attached appender(s)
+if \c logger is enabled for <code>ERROR</code> events.
@param logger the logger to be used.
@param condition condition
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
*/
-#define LOG4CXX_ASSERT_FMT(logger, condition, ...) do { \
+#define LOG4CXX_ASSERT_FMT(logger, condition, fmt, ...) do { \
if (!(condition) && ::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
LOG4CXX_STACKTRACE \
- logger->addEvent(::LOG4CXX_NS::Level::getError(), fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(::LOG4CXX_NS::Level::getError(), ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
#else
#define LOG4CXX_ERROR(logger, message)
-#define LOG4CXX_ERROR_FMT(logger, ...)
+#define LOG4CXX_ERROR_FMT(logger, fmt, ...)
#define LOG4CXX_ASSERT(logger, condition, message)
-#define LOG4CXX_ASSERT_FMT(logger, condition, ...)
+#define LOG4CXX_ASSERT_FMT(logger, condition, fmt, ...)
#endif
#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 50000
@@ -2260,7 +2289,6 @@
@param logger the logger to be used.
@param message a valid r-value expression of an <code>operator<<(std::ostream&. ...)</code> overload.
-<p>Example:
~~~{.cpp}
LOG4CXX_FATAL(m_log, m_renderSystem->getName() << " is not supported");
~~~
@@ -2271,17 +2299,22 @@
logger->addEvent(::LOG4CXX_NS::Level::getFatal(), oss_.extract_str(oss_ << message), LOG4CXX_LOCATION); }} while (0)
/**
-Add a new logging event containing libfmt formatted <code>...</code> to attached appender(s) if \c logger is enabled for <code>FATAL</code> events.
+Add a new logging event containing a message defined by \c fmt and <code>...</code> to attached appender(s) if \c logger is enabled for <code>FATAL</code> events.
@param logger the logger to be used.
-@param ... The format string and parameters that define the log message.
+@param fmt the layout of the message.
+@param ... the variable parts of the message.
+
+~~~{.cpp}
+LOG4CXX_FATAL_FMT(m_log, "{} is not supported", m_renderSystem->getName());
+~~~
*/
-#define LOG4CXX_FATAL_FMT(logger, ...) do { \
+#define LOG4CXX_FATAL_FMT(logger, fmt, ...) do { \
if (::LOG4CXX_NS::Logger::isFatalEnabledFor(logger)) {\
- logger->addEvent(::LOG4CXX_NS::Level::getFatal(), fmt::format( __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
+ logger->addEvent(::LOG4CXX_NS::Level::getFatal(), ::LOG4CXX_FORMAT_NS::format(fmt, __VA_ARGS__ ), LOG4CXX_LOCATION); }} while (0)
#else
#define LOG4CXX_FATAL(logger, message)
-#define LOG4CXX_FATAL_FMT(logger, ...)
+#define LOG4CXX_FATAL_FMT(logger, fmt, ...)
#endif
/**
diff --git a/src/site/markdown/concepts.md b/src/site/markdown/concepts.md
index 835158d..bb3e195 100644
--- a/src/site/markdown/concepts.md
+++ b/src/site/markdown/concepts.md
@@ -199,18 +199,20 @@
This leads to very awkward code to read and write, especially as iostreams don't
support positional arguments at all.
-In order to get around this, one popular library(that has been standardized as
-part of C++20) is [{fmt}](https://fmt.dev/latest/index.html). Supporting
-positional arguments and printf-like formatting, it makes for much clearer
-code like the following:
+In order to get around this, Log4cxx provides a family of macros that
+support positional arguments and printf-like formatting, which makes for much clearer
+(and more efficient) code like the following:
~~~{.cpp}
LOG4CXX_INFO_FMT( rootLogger, "Numbers can be formatted with a format string {:.1f} and as hex: {:x}", 22.456, 123 );
~~~
+The `LOG4CXX_[level]_FMT` macros use the [{fmt}](https://fmt.dev/latest/index.html) library by default.
Note that Log4cxx does not include a copy of {fmt}, so you must include the
correct headers and linker flags in order to use the `LOG4CXX_[level]_FMT`
family of macros.
+Provide `LOG4CXX_FORMAT_NS=std` to the preprocessor to have
+the `LOG4CXX_[level]_FMT` macros use the standard library version of [format](https://en.cppreference.com/w/cpp/utility/format/format).
As with the standard logger macros, these macros will also be compiled out
if the `LOG4CXX_THRESHOLD` macro is set to a level that will compile out
diff --git a/src/site/markdown/development/build-cmake.md b/src/site/markdown/development/build-cmake.md
index 9b6355f..bbe54ce 100644
--- a/src/site/markdown/development/build-cmake.md
+++ b/src/site/markdown/development/build-cmake.md
@@ -72,6 +72,7 @@
| -DPREFER_BOOST=on | Prefer the Boost version of dependent libraries over standard library |
| -DLOG4CXX_QT_SUPPORT=ON | Enable QString API and log4cxx::qt namespace methods, requires QtCore, choice of ON, OFF (default). |
| -DLOG4CXX_EVENTS_AT_EXIT=ON | Prevent static data cleanup to allow event logging during application exit. |
+| -DLOG4CXX_FORMAT_NAMESPACE=std | Make the `LOG4CXX_[level]_FMT` macros use [std::format](https://en.cppreference.com/w/cpp/utility/format/format) by default. |
# Platform specific notes:
diff --git a/src/site/markdown/macros-influencing-log4cxx.md b/src/site/markdown/macros-influencing-log4cxx.md
index 40975f2..dea4570 100644
--- a/src/site/markdown/macros-influencing-log4cxx.md
+++ b/src/site/markdown/macros-influencing-log4cxx.md
@@ -32,3 +32,4 @@
| LOG4CXX\_THRESHOLD | Used to determine if log messages are compiled in or not. A higher value causes more messages to be compiled out. See [removing log statements](usage.html#removing-log-statements) for more information. |
| LOG4CXX\_DISABLE\_LOCATION\_INFO | Define this macro to disable location information on log statements. Location information includes the filename, class name, method name, and line number |
| LOG4CXX\_ENABLE\_STACKTRACE | Define this macro to cause a stacktrace string to be inserted into the MDC with a key of 'stacktrace'. This requires Boost Stacktrace or C++23 stacktrace to be available when compiling your application. When using the PatternLayout, print out the stacktrace using the `%%X{stacktrace}` specifier. See [stacktrace support](stacktrace-support.html) for more information. |
+| LOG4CXX_FORMAT_NS | Override the namespace that LOG4CXX_XXXX_FMT macros use by default. The value can be either 'fmt' or 'std'. You would use the value 'std' if Log4cxx was built with LOG4CXX_FORMAT_NAMESPACE=fmt. |
\ No newline at end of file
diff --git a/src/test/cpp/benchmark/benchmark.cpp b/src/test/cpp/benchmark/benchmark.cpp
index e650848..3c5a28d 100644
--- a/src/test/cpp/benchmark/benchmark.cpp
+++ b/src/test/cpp/benchmark/benchmark.cpp
@@ -4,7 +4,11 @@
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/asyncappender.h>
+#if LOG4CXX_USING_STD_FORMAT
+#include <format>
+#else
#include <fmt/format.h>
+#endif
#include <benchmark/benchmark.h>
#include <thread>
#include <cstdlib>
@@ -136,7 +140,7 @@
{
for (auto _ : state)
{
- LOG4CXX_INFO_FMT(m_logger, "This is a static string to see what happens");
+ LOG4CXX_INFO_FMT(m_logger, "This is a static string to see what happens", 0);
}
}
BENCHMARK_REGISTER_F(benchmarker, logStaticStringFMT)->Name("Logging static string with FMT");
diff --git a/src/test/cpp/throughput/log4cxxbenchmarker.cpp b/src/test/cpp/throughput/log4cxxbenchmarker.cpp
index 0a1568d..42fedbf 100644
--- a/src/test/cpp/throughput/log4cxxbenchmarker.cpp
+++ b/src/test/cpp/throughput/log4cxxbenchmarker.cpp
@@ -20,8 +20,11 @@
#include <log4cxx/patternlayout.h>
#include <log4cxx/appenderskeleton.h>
+#if LOG4CXX_USING_STD_FORMAT
+#include <format>
+#else
#include <fmt/format.h>
-
+#endif
namespace LOG4CXX_NS
{
@@ -174,7 +177,7 @@
for ( int x = 0; x < howmany; x++ )
{
- LOG4CXX_INFO_FMT( logger, "This is a static string to see what happens");
+ LOG4CXX_INFO_FMT( logger, "This is a static string to see what happens", 0);
}
}
diff --git a/src/test/cpp/throughput/throughput-main.cpp b/src/test/cpp/throughput/throughput-main.cpp
index 2380756..6671c57 100644
--- a/src/test/cpp/throughput/throughput-main.cpp
+++ b/src/test/cpp/throughput/throughput-main.cpp
@@ -24,9 +24,13 @@
#include <string>
#include <thread>
+#if LOG4CXX_USING_STD_FORMAT
+#include <format>
+#else
#include <fmt/core.h>
#include <fmt/chrono.h>
#include <fmt/ostream.h>
+#endif
#include "log4cxxbenchmarker.h"
using log4cxx::LogString;
@@ -182,12 +186,12 @@
return 1;
}
- LOG4CXX_INFO_FMT(console, "Benchmarking library only(no writing out):");
+ LOG4CXX_INFO_FMT(console, "Benchmarking library only(no writing out):", 0);
bench_log4cxx_single_threaded(iters);
bench_log4cxx_multi_threaded(threads, iters);
bench_log4cxx_multi_threaded_disabled(threads, iters);
- LOG4CXX_INFO_FMT(console, "Results for use in spreadsheet:");
+ LOG4CXX_INFO_FMT(console, "Results for use in spreadsheet:", 0);
for ( uint64_t result : results )
{