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
