You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sw...@apache.org on 2023/04/21 05:13:16 UTC
[logging-log4cxx] 01/01: Allow message strings containing quote characters to be logged to a database
This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch add-sql-message
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
commit 2dd631130f517953bb4044dd09797c9269cd68d8
Author: Stephen Webb <sw...@gmail.com>
AuthorDate: Fri Apr 21 15:12:46 2023 +1000
Allow message strings containing quote characters to be logged to a database
---
src/main/cpp/messagepatternconverter.cpp | 67 +++++++++++++++++-----
src/main/include/log4cxx/db/odbcappender.h | 2 +-
src/test/cpp/db/odbcappendertestcase.cpp | 2 +-
.../input/xml/odbcAppenderDSN-Log4cxxTest.xml | 2 +-
4 files changed, 56 insertions(+), 17 deletions(-)
diff --git a/src/main/cpp/messagepatternconverter.cpp b/src/main/cpp/messagepatternconverter.cpp
index 83269d97..c31e3ef2 100644
--- a/src/main/cpp/messagepatternconverter.cpp
+++ b/src/main/cpp/messagepatternconverter.cpp
@@ -20,31 +20,70 @@
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/spi/location/locationinfo.h>
-using namespace log4cxx;
-using namespace log4cxx::pattern;
-using namespace log4cxx::spi;
-using namespace log4cxx::helpers;
+namespace log4cxx
+{
+namespace pattern
+{
IMPLEMENT_LOG4CXX_OBJECT(MessagePatternConverter)
+/**
+ * Formats the message of an logging event for a quoted context
+ */
+class QuotedMessagePatternConverter : public LoggingEventPatternConverter
+{
+ logchar m_quote;
+ public:
+ QuotedMessagePatternConverter(logchar quote)
+ : LoggingEventPatternConverter(LOG4CXX_STR("Message"), LOG4CXX_STR("quoted"))
+ , m_quote(quote)
+ {}
-MessagePatternConverter::MessagePatternConverter() :
- LoggingEventPatternConverter(LOG4CXX_STR("Message"),
- LOG4CXX_STR("message"))
+ using LoggingEventPatternConverter::format;
+
+ void format
+ ( const spi::LoggingEventPtr& event
+ , LogString& toAppendTo
+ , helpers::Pool& p
+ ) const override
+ {
+ auto& input = event->getRenderedMessage();
+ size_t endIndex, startIndex = 0;
+ while ((endIndex = input.find(m_quote, startIndex)) != input.npos)
+ {
+ toAppendTo.append(input.substr(startIndex, endIndex - startIndex + 1));
+ toAppendTo += m_quote;
+ startIndex = endIndex + 1;
+ }
+ toAppendTo.append(input.substr(startIndex));
+ }
+};
+
+MessagePatternConverter::MessagePatternConverter()
+ : LoggingEventPatternConverter(LOG4CXX_STR("Message")
+ , LOG4CXX_STR("message"))
{
}
PatternConverterPtr MessagePatternConverter::newInstance(
- const std::vector<LogString>& /* options */)
+ const std::vector<LogString>& options)
{
- static PatternConverterPtr def = std::make_shared<MessagePatternConverter>();
- return def;
+ if (options.empty() || options.front().empty())
+ {
+ static PatternConverterPtr def = std::make_shared<MessagePatternConverter>();
+ return def;
+ }
+ return std::make_shared<QuotedMessagePatternConverter>(options.front().front());
}
-void MessagePatternConverter::format(
- const LoggingEventPtr& event,
- LogString& toAppendTo,
- Pool& /* p */) const
+void MessagePatternConverter::format
+ ( const spi::LoggingEventPtr& event
+ , LogString& toAppendTo
+ , helpers::Pool& /* p */
+ ) const
{
toAppendTo.append(event->getRenderedMessage());
}
+} // namespace pattern
+} // namespace log4cxx
+
diff --git a/src/main/include/log4cxx/db/odbcappender.h b/src/main/include/log4cxx/db/odbcappender.h
index f50f64b8..aa85aaf6 100644
--- a/src/main/include/log4cxx/db/odbcappender.h
+++ b/src/main/include/log4cxx/db/odbcappender.h
@@ -103,7 +103,7 @@ An example configuration that writes to the data source named "LoggingDSN" is:
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
appender name="SqlAppender" class="ODBCAppender">
<param name="DSN" value="LoggingDSN"/>
- <param name="sql" value="INSERT INTO [SomeDatabaseName].[SomeUserName].[SomeTableName] ([Thread],[LogName],[LogTime],[LogLevel],[FileName],[FileLine],[Message]) VALUES ('%t', '%c','%d{dd MMM yyyy HH:mm:ss.SSS}','%p','%f','%L','%m')" />
+ <param name="sql" value="INSERT INTO [SomeDatabaseName].[SomeUserName].[SomeTableName] ([Thread],[LogName],[LogTime],[LogLevel],[FileName],[FileLine],[Message]) VALUES ('%t', '%c','%d{dd MMM yyyy HH:mm:ss.SSS}','%p','%f','%L','%m{'}')" />
</appender>
<appender name="ASYNC" class="AsyncAppender">
<param name="BufferSize" value="1000"/>
diff --git a/src/test/cpp/db/odbcappendertestcase.cpp b/src/test/cpp/db/odbcappendertestcase.cpp
index 14c91328..ca568aed 100644
--- a/src/test/cpp/db/odbcappendertestcase.cpp
+++ b/src/test/cpp/db/odbcappendertestcase.cpp
@@ -88,7 +88,7 @@ class ODBCAppenderTestCase : public AppenderSkeletonTestCase
auto odbc = Logger::getLogger("DB.UnitTest");
for (int i = 0; i < 100; ++i)
{
- LOG4CXX_INFO(odbc, "Message " << i);
+ LOG4CXX_INFO(odbc, "Message '" << i << "'");
apr_sleep(30000);
}
LOG4CXX_INFO(odbc, "Last message");
diff --git a/src/test/resources/input/xml/odbcAppenderDSN-Log4cxxTest.xml b/src/test/resources/input/xml/odbcAppenderDSN-Log4cxxTest.xml
index 3e035869..ff5bcbe2 100644
--- a/src/test/resources/input/xml/odbcAppenderDSN-Log4cxxTest.xml
+++ b/src/test/resources/input/xml/odbcAppenderDSN-Log4cxxTest.xml
@@ -27,7 +27,7 @@
</appender>
<appender name="SqlAppender" class="ODBCAppender">
<param name="DSN" value="Log4cxxTest"/>
- <param name="sql" value="INSERT INTO [ApplicationLogs].[dbo].[UnitTestLog] ([Thread],[LogName],[LogTime],[LogLevel],[FileName],[FileLine],[Message]) VALUES ('%t', '%c','%d{dd MMM yyyy HH:mm:ss.SSS}','%p','%f','%L','%m')" />
+ <param name="sql" value="INSERT INTO [ApplicationLogs].[dbo].[UnitTestLog] ([Thread],[LogName],[LogTime],[LogLevel],[FileName],[FileLine],[Message]) VALUES ('%t', '%c','%d{dd MMM yyyy HH:mm:ss.SSS}','%p','%f','%L','%m{'}')" />
<!--param name="User" value="dbo"/-->
<!--param name="Password" value="myLog4cxxTestPassword"/-->
</appender>