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/25 05:32:25 UTC

[logging-log4cxx] 01/01: ODBCAppender support for logging a single value or all values (as JASON) of an event's mapped diagnostic context

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 <sw...@gmail.com>
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