This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch mdc_pattern_converter
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git

commit 875a0f655844bbe549303f0e1dccaefb5190a8d2
Author: Stephen Webb <[email protected]>
AuthorDate: Tue Apr 25 15:32:05 2023 +1000

    ODBCAppender support for logging a single value or all values (as JASON) of 
an event's mapped diagnostic context
---
 src/main/cpp/CMakeLists.txt                        |  1 +
 src/main/cpp/jsonlayout.cpp                        |  2 +-
 src/main/cpp/mdcpatternconverter.cpp               | 61 ++++++++++++++++++++++
 src/main/cpp/odbcappender.cpp                      | 25 ++++++++-
 src/main/include/log4cxx/db/odbcappender.h         | 26 ++++-----
 src/main/include/log4cxx/jsonlayout.h              |  2 +-
 .../include/log4cxx/pattern/mdcpatternconverter.h  | 57 ++++++++++++++++++++
 7 files changed, 158 insertions(+), 16 deletions(-)

diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index fcf25b88..55c10381 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -143,6 +143,7 @@ target_sources(log4cxx
   nameabbreviator.cpp
   namepatternconverter.cpp
   ndc.cpp
+  mdcpatternconverter.cpp
   ndcpatternconverter.cpp
   nteventlogappender.cpp
   odbcappender.cpp
diff --git a/src/main/cpp/jsonlayout.cpp b/src/main/cpp/jsonlayout.cpp
index aca87f51..6e8a7ce7 100644
--- a/src/main/cpp/jsonlayout.cpp
+++ b/src/main/cpp/jsonlayout.cpp
@@ -171,7 +171,7 @@ void JSONLayout::format(LogString& output,
 }
 
 void JSONLayout::appendQuotedEscapedString(LogString& buf,
-       const LogString& input) const
+       const LogString& input)
 {
        /* add leading quote */
        buf.push_back(0x22);
diff --git a/src/main/cpp/mdcpatternconverter.cpp 
b/src/main/cpp/mdcpatternconverter.cpp
new file mode 100644
index 00000000..9b4ac2ef
--- /dev/null
+++ b/src/main/cpp/mdcpatternconverter.cpp
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <log4cxx/pattern/mdcpatternconverter.h>
+#include <log4cxx/private/patternconverter_priv.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/jsonlayout.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(MDCPatternConverter)
+
+MDCPatternConverter::MDCPatternConverter
+       ( const LogString&              name
+       , const LogString&              style
+       , const std::vector<LogString>& options
+       )
+       : 
LoggingEventPatternConverter(std::make_unique<PatternConverter::PatternConverterPrivate>(name,
 style))
+{
+}
+
+void MDCPatternConverter::format
+       ( const spi::LoggingEventPtr& event
+       , LogString&                  toAppendTo
+       , helpers::Pool&           /* p */
+       ) const
+{
+       if (m_priv->name.empty())
+       {
+               bool first = true;
+               for (auto key : event->getMDCKeySet())
+               {
+                       toAppendTo.append(first ? LOG4CXX_STR("{") : 
LOG4CXX_STR(","));
+                       JSONLayout::appendQuotedEscapedString(toAppendTo, key);
+                       toAppendTo.append(LOG4CXX_STR(":"));
+                       LogString value;
+                       event->getMDC(key, value);
+                       JSONLayout::appendQuotedEscapedString(toAppendTo, 
value);
+                       first = false;
+               }
+               if (!first)
+                       toAppendTo.append(LOG4CXX_STR("}"));
+       }
+       else
+               event->getMDC(m_priv->name, toAppendTo);
+}
diff --git a/src/main/cpp/odbcappender.cpp b/src/main/cpp/odbcappender.cpp
index 7a2ed5ab..8c927798 100644
--- a/src/main/cpp/odbcappender.cpp
+++ b/src/main/cpp/odbcappender.cpp
@@ -20,6 +20,7 @@
 #include <log4cxx/helpers/stringhelper.h>
 #include <log4cxx/helpers/transcoder.h>
 #include <log4cxx/patternlayout.h>
+#include <log4cxx/pattern/mdcpatternconverter.h>
 #include <apr_strings.h>
 #include <apr_time.h>
 #include <cmath> // std::pow
@@ -201,9 +202,29 @@ void ODBCAppender::activateOptions(log4cxx::helpers::Pool&)
        auto specs = getFormatSpecifiers();
        for (auto& name : _priv->mappedName)
        {
-               auto pItem = specs.find(StringHelper::toLowerCase(name));
+               auto lowerName = StringHelper::toLowerCase(name);
+               auto pItem = specs.find(lowerName);
                if (specs.end() == pItem)
-                       LogLog::error(name + LOG4CXX_STR(" is not a supported 
ColumnMapping value"));
+               {
+                       if (lowerName.size() < 3 || LOG4CXX_STR("mdc") != 
lowerName.substr(0, 3))
+                               LogLog::error(name + LOG4CXX_STR(" is not a 
supported ColumnMapping value"));
+                       else if (lowerName[3] == 0x7B /* '{' */) // A single 
MDC entry?
+                       {
+                               auto index = lowerName.find(0x7D /* '}' */, 4);
+                               size_t len = (lowerName.npos == index ? 
lowerName.size() : index) - 4;
+                               ODBCAppenderPriv::DataBinding paramData{ 0, 0, 
0, 0, 0 };
+                               paramData.converter = 
std::make_shared<MDCPatternConverter>(lowerName.substr(4, len));
+                               _priv->parameterValue.push_back(paramData);
+                       }
+                       else if (lowerName.size() == 3) // Dump all MDC entries?
+                       {
+                               ODBCAppenderPriv::DataBinding paramData{ 0, 0, 
0, 0, 0 };
+                               paramData.converter = 
std::make_shared<MDCPatternConverter>();
+                               _priv->parameterValue.push_back(paramData);
+                       }
+                       else
+                               LogLog::error(name + LOG4CXX_STR(" is not a 
supported ColumnMapping value"));
+               }
                else
                {
                        ODBCAppenderPriv::DataBinding paramData{ 0, 0, 0, 0, 0 
};
diff --git a/src/main/include/log4cxx/db/odbcappender.h 
b/src/main/include/log4cxx/db/odbcappender.h
index 60db2ccb..c842cf5e 100644
--- a/src/main/include/log4cxx/db/odbcappender.h
+++ b/src/main/include/log4cxx/db/odbcappender.h
@@ -81,18 +81,20 @@ The following <b>param</b> elements are optional:
   One element for each "?" in the <b>sql</b> statement
   in a sequence corresponding to the columns in the insert statement.
   The following values are supported:
-  - logger
-  - level
-  - thread
-  - threadname
-  - time
-  - shortfilename
-  - fullfilename
-  - line
-  - class
-  - method
-  - message
-  - ndc
+  - <b>logger</b> - the name of the logger that generated the logging event
+  - <b>level</b> - the level of the logging event
+  - <b>thread</b> - the thread number as a hex string that generated the 
logging event
+  - <b>threadname</b> - the name assigned to the thread that generated the 
logging event
+  - <b>time</b> - a datetime or datetime2 SQL field type at which the event 
was generated
+  - <b>shortfilename</b> - the basename of the file containing the logging 
statement
+  - <b>fullfilename</b> - the path of the file containing the logging statement
+  - <b>line</b> - the position in the file at which the logging event was 
generated
+  - <b>class</b> - the class from which the logging event was generated
+  - <b>method</b> - the function in which the logging event was generated
+  - <b>message</b> - the data sent by the logging statement
+  - <b>mdc</b> - A JASON format string of all entries in the logging thread's 
mapped diagnostic context
+  - <b>mdc{key}</b> - the value associated with the <b>key</b> entry in the 
logging thread's mapped diagnostic context 
+  - <b>ndc</b> - the last entry the logging thread's nested diagnostic context 
 
 <p>For use as a base class:
 
diff --git a/src/main/include/log4cxx/jsonlayout.h 
b/src/main/include/log4cxx/jsonlayout.h
index 0dca1d01..63affafe 100644
--- a/src/main/include/log4cxx/jsonlayout.h
+++ b/src/main/include/log4cxx/jsonlayout.h
@@ -34,7 +34,6 @@ class LOG4CXX_EXPORT JSONLayout : public Layout
                LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(JSONLayoutPrivate, m_priv)
 
        protected:
-               void appendQuotedEscapedString(LogString& buf, const LogString& 
input) const;
                void appendSerializedMDC(LogString& buf,
                        const spi::LoggingEventPtr& event) const;
                void appendSerializedNDC(LogString& buf,
@@ -43,6 +42,7 @@ class LOG4CXX_EXPORT JSONLayout : public Layout
                        const spi::LoggingEventPtr& event, 
log4cxx::helpers::Pool& p) const;
 
        public:
+               static void appendQuotedEscapedString(LogString& buf, const 
LogString& input);
                DECLARE_LOG4CXX_OBJECT(JSONLayout)
                BEGIN_LOG4CXX_CAST_MAP()
                LOG4CXX_CAST_ENTRY(JSONLayout)
diff --git a/src/main/include/log4cxx/pattern/mdcpatternconverter.h 
b/src/main/include/log4cxx/pattern/mdcpatternconverter.h
new file mode 100644
index 00000000..46255ee5
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/mdcpatternconverter.h
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LOG4CXX_PATTERN_MDC_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_MDC_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx
+{
+namespace pattern
+{
+
+
+/**
+ * Provides all key value pairs in JASON or a single value from an event's 
mapped diagnostic context
+ */
+class LOG4CXX_EXPORT MDCPatternConverter : public LoggingEventPatternConverter
+{
+       public:
+               DECLARE_LOG4CXX_PATTERN(MDCPatternConverter)
+               BEGIN_LOG4CXX_CAST_MAP()
+               LOG4CXX_CAST_ENTRY(MDCPatternConverter)
+               LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+               END_LOG4CXX_CAST_MAP()
+
+               MDCPatternConverter
+                       ( const LogString&              name = LogString()
+                       , const LogString&              style = LogString()
+                       , const std::vector<LogString>& options = 
std::vector<LogString>()
+                       );
+
+               using LoggingEventPatternConverter::format;
+
+               void format
+                       ( const spi::LoggingEventPtr& event
+                       , LogString&                  toAppendTo
+                       , helpers::Pool&              p
+                       ) const override;
+};
+}
+}
+#endif

Reply via email to