This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
The following commit(s) were added to refs/heads/master by this push:
new d91bf594 Add JSONLayout to the Google benchmark tests (#521)
d91bf594 is described below
commit d91bf59401a9a643b60dc5551abf8f70fac6f9b5
Author: Stephen Webb <[email protected]>
AuthorDate: Wed Aug 20 09:12:38 2025 +1000
Add JSONLayout to the Google benchmark tests (#521)
* Reduce JSONLayout overhead by up to 20%
---
src/main/cpp/jsonlayout.cpp | 27 ++++-----
src/test/cpp/benchmark/benchmark.cpp | 107 +++++++++++++++++++++++++++++++++++
2 files changed, 119 insertions(+), 15 deletions(-)
diff --git a/src/main/cpp/jsonlayout.cpp b/src/main/cpp/jsonlayout.cpp
index 3e0abf48..9b286aff 100644
--- a/src/main/cpp/jsonlayout.cpp
+++ b/src/main/cpp/jsonlayout.cpp
@@ -20,7 +20,8 @@
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/optionconverter.h>
-#include <log4cxx/helpers/iso8601dateformat.h>
+#include <log4cxx/helpers/cacheddateformat.h>
+#include <log4cxx/helpers/simpledateformat.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/transcoder.h>
@@ -37,7 +38,6 @@ struct JSONLayout::JSONLayoutPrivate
JSONLayoutPrivate() :
locationInfo(false),
prettyPrint(false),
- dateFormat(),
ppIndentL1(LOG4CXX_STR(" ")),
ppIndentL2(LOG4CXX_STR(" ")),
expectedPatternLength(100),
@@ -47,7 +47,10 @@ struct JSONLayout::JSONLayoutPrivate
bool locationInfo; //= false
bool prettyPrint; //= false
- helpers::ISO8601DateFormat dateFormat;
+ pattern::CachedDateFormat dateFormat
+ {
std::make_shared<helpers::SimpleDateFormat>(LOG4CXX_STR("yyyy-MM-dd
HH:mm:ss,SSS"))
+ ,
pattern::CachedDateFormat::getMaximumCacheValidity(LOG4CXX_STR("yyyy-MM-dd
HH:mm:ss,SSS"))
+ };
LogString ppIndentL1;
LogString ppIndentL2;
@@ -138,12 +141,9 @@ void JSONLayout::format(LogString& output,
output.append(m_priv->ppIndentL1);
}
- appendQuotedEscapedString(output, LOG4CXX_STR("timestamp"));
- output.append(LOG4CXX_STR(": "));
- LogString timestamp;
- m_priv->dateFormat.format(timestamp, event->getTimeStamp(), p);
- appendQuotedEscapedString(output, timestamp);
- output.append(LOG4CXX_STR(","));
+ output.append(LOG4CXX_STR("\"timestamp\": \""));
+ m_priv->dateFormat.format(output, event->getTimeStamp(), p);
+ output.append(LOG4CXX_STR("\","));
output.append(m_priv->prettyPrint ? LOG4CXX_EOL : LOG4CXX_STR(" "));
if (m_priv->threadInfo)
@@ -164,8 +164,7 @@ void JSONLayout::format(LogString& output,
output.append(m_priv->ppIndentL1);
}
- appendQuotedEscapedString(output, LOG4CXX_STR("level"));
- output.append(LOG4CXX_STR(": "));
+ output.append(LOG4CXX_STR("\"level\": "));
LogString level;
event->getLevel()->toString(level);
appendQuotedEscapedString(output, level);
@@ -177,8 +176,7 @@ void JSONLayout::format(LogString& output,
output.append(m_priv->ppIndentL1);
}
- appendQuotedEscapedString(output, LOG4CXX_STR("logger"));
- output.append(LOG4CXX_STR(": "));
+ output.append(LOG4CXX_STR("\"logger\": "));
appendQuotedEscapedString(output, event->getLoggerName());
output.append(LOG4CXX_STR(","));
output.append(m_priv->prettyPrint ? LOG4CXX_EOL : LOG4CXX_STR(" "));
@@ -188,8 +186,7 @@ void JSONLayout::format(LogString& output,
output.append(m_priv->ppIndentL1);
}
- appendQuotedEscapedString(output, LOG4CXX_STR("message"));
- output.append(LOG4CXX_STR(": "));
+ output.append(LOG4CXX_STR("\"message\": "));
appendQuotedEscapedString(output, event->getMessage());
appendSerializedMDC(output, event);
diff --git a/src/test/cpp/benchmark/benchmark.cpp
b/src/test/cpp/benchmark/benchmark.cpp
index 4fce4434..873d2cd7 100644
--- a/src/test/cpp/benchmark/benchmark.cpp
+++ b/src/test/cpp/benchmark/benchmark.cpp
@@ -1,11 +1,13 @@
#include <log4cxx/logger.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/patternlayout.h>
+#include <log4cxx/jsonlayout.h>
#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/asyncappender.h>
#include <log4cxx/net/smtpappender.h>
+#include <log4cxx/net/xmlsocketappender.h>
#include <log4cxx/fileappender.h>
#if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER
#include <log4cxx/rolling/multiprocessrollingfileappender.h>
@@ -22,6 +24,8 @@
#include <cstdlib>
#include <iomanip>
+#define LOCALHOST_HAS_FLUENT_BIT_RUNNING_ON_PORT_5170 0
+
using namespace log4cxx;
class NullWriterAppender : public AppenderSkeleton
@@ -69,6 +73,37 @@ public:
}
};
+class BenchmarkJSONFileAppender : public FileAppender
+{
+public:
+ BenchmarkJSONFileAppender()
+ {
+ setLayout(std::make_shared<JSONLayout>());
+ auto tempDir =
helpers::OptionConverter::getSystemProperty(LOG4CXX_STR("TEMP"),
LOG4CXX_STR("/tmp"));
+ setFile(tempDir + LOG4CXX_STR("/") +
LOG4CXX_STR("benchmark.json"));
+ setAppend(false);
+ setBufferedIO(true);
+ helpers::Pool p;
+ activateOptions(p);
+ }
+};
+
+#if LOCALHOST_HAS_FLUENT_BIT_RUNNING_ON_PORT_5170
+class BenchmarkFluentbitAppender : public net::XMLSocketAppender
+{
+public:
+ BenchmarkFluentbitAppender()
+ {
+ setName(LOG4CXX_STR("FluentbitAppender"));
+ setLayout(std::make_shared<JSONLayout>());
+ setRemoteHost(LOG4CXX_STR("localhost"));
+ setPort(5170);
+ helpers::Pool p;
+ activateOptions(p);
+ }
+};
+#endif
+
#if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER
class BenchmarkMultiprocessFileAppender : public
rolling::MultiprocessRollingFileAppender
{
@@ -100,6 +135,10 @@ public: // Attributes
LoggerPtr m_logger = getLogger();
LoggerPtr m_asyncLogger = getAsyncLogger();
LoggerPtr m_fileLogger = getFileLogger();
+ LoggerPtr m_JSONLogger = getJSONFileLogger();
+#if LOCALHOST_HAS_FLUENT_BIT_RUNNING_ON_PORT_5170
+ LoggerPtr m_socketLogger = getFluentbitLogger();
+#endif
#if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER
LoggerPtr m_multiprocessLogger = getMultiprocessLogger();
#endif
@@ -202,6 +241,46 @@ public: // Class methods
return result;
}
+ static LoggerPtr getJSONFileLogger()
+ {
+ LogString name = LOG4CXX_STR("benchmark.fixture.JSONfile");
+ auto r = LogManager::getLoggerRepository();
+ LoggerPtr result;
+ if (!(result = r->exists(name)))
+ {
+ result = r->getLogger(name);
+ result->setAdditivity(false);
+ result->setLevel(Level::getInfo());
+ auto writer =
std::make_shared<BenchmarkJSONFileAppender>();
+ writer->setName(LOG4CXX_STR("JSONFileAppender"));
+ writer->setBufferedIO(true);
+ helpers::Pool p;
+ writer->activateOptions(p);
+ result->addAppender(writer);
+ }
+ return result;
+ }
+
+#if LOCALHOST_HAS_FLUENT_BIT_RUNNING_ON_PORT_5170
+ static LoggerPtr getFluentbitLogger()
+ {
+ LogString name = LOG4CXX_STR("benchmark.fixture.Fluentbit");
+ auto r = LogManager::getLoggerRepository();
+ LoggerPtr result;
+ if (!(result = r->exists(name)))
+ {
+ result = r->getLogger(name);
+ result->setAdditivity(false);
+ result->setLevel(Level::getInfo());
+ auto writer =
std::make_shared<BenchmarkFluentbitAppender>();
+ helpers::Pool p;
+ writer->activateOptions(p);
+ result->addAppender(writer);
+ }
+ return result;
+ }
+#endif
+
#if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER
static LoggerPtr getMultiprocessLogger()
{
@@ -357,6 +436,34 @@ BENCHMARK_DEFINE_F(benchmarker,
fileIntPlusFloatValueMessageBuffer)(benchmark::S
BENCHMARK_REGISTER_F(benchmarker,
fileIntPlusFloatValueMessageBuffer)->Name("Logging int+float using
MessageBuffer, pattern: %d %m%n");
BENCHMARK_REGISTER_F(benchmarker,
fileIntPlusFloatValueMessageBuffer)->Name("Logging int+float using
MessageBuffer, pattern: %d %m%n")->Threads(benchmarker::threadCount());
+BENCHMARK_DEFINE_F(benchmarker,
fileIntPlusFloatValueMessageBufferJSON)(benchmark::State& state)
+{
+ int x = 0;
+ for (auto _ : state)
+ {
+ auto f = static_cast<float>(rand()) /
static_cast<float>(RAND_MAX);
+ LOG4CXX_INFO( m_JSONLogger, "Hello: message number " << ++x
+ << " pseudo-random float " << std::setprecision(3) <<
std::fixed << f);
+ }
+}
+BENCHMARK_REGISTER_F(benchmarker,
fileIntPlusFloatValueMessageBufferJSON)->Name("Logging int+float using
MessageBuffer, JSON");
+BENCHMARK_REGISTER_F(benchmarker,
fileIntPlusFloatValueMessageBufferJSON)->Name("Logging int+float using
MessageBuffer, JSON")->Threads(benchmarker::threadCount());
+
+#if LOCALHOST_HAS_FLUENT_BIT_RUNNING_ON_PORT_5170
+BENCHMARK_DEFINE_F(benchmarker,
socketIntPlusFloatValueMessageBufferJSON)(benchmark::State& state)
+{
+ int x = 0;
+ for (auto _ : state)
+ {
+ auto f = static_cast<float>(rand()) /
static_cast<float>(RAND_MAX);
+ LOG4CXX_INFO( m_socketLogger, "Hello: message number " << ++x
+ << " pseudo-random float " << std::setprecision(3) <<
std::fixed << f);
+ }
+}
+BENCHMARK_REGISTER_F(benchmarker,
socketIntPlusFloatValueMessageBufferJSON)->Name("Sending int+float using
MessageBuffer, JSON");
+BENCHMARK_REGISTER_F(benchmarker,
socketIntPlusFloatValueMessageBufferJSON)->Name("Sending int+float using
MessageBuffer, JSON")->Threads(benchmarker::threadCount());
+#endif
+
#if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER
BENCHMARK_DEFINE_F(benchmarker,
multiprocessFileIntPlusFloatValueMessageBuffer)(benchmark::State& state)
{