This is an automated email from the ASF dual-hosted git repository. rmiddleton pushed a commit to branch LOGCXX-567 in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
commit 8f1e6869d56d325c109153ce9d5f205c73c122de Author: Robert Middleton <[email protected]> AuthorDate: Fri Dec 9 21:09:18 2022 -0500 LOGCXX-567 Add optional stacktrace support --- CMakeLists.txt | 4 +- src/main/cpp/CMakeLists.txt | 1 + src/main/cpp/loggingevent.cpp | 17 ++++++ src/main/cpp/patternlayout.cpp | 3 ++ src/main/cpp/stacktracepatternconverter.cpp | 50 +++++++++++++++++ src/main/include/CMakeLists.txt | 7 +++ .../log4cxx/pattern/stacktracepatternconverter.h | 62 ++++++++++++++++++++++ src/main/include/log4cxx/patternlayout.h | 9 ++++ .../include/log4cxx/private/log4cxx_private.h.in | 1 + src/main/include/log4cxx/spi/loggingevent.h | 9 ++++ 10 files changed, 162 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fca0f7e2..1cee0564 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,8 +197,9 @@ get_directory_property( SHARED_MUTEX_IMPL DIRECTORY src/main/include DEFINITION get_directory_property( ATOMIC_IMPL DIRECTORY src/main/include DEFINITION ATOMIC_IMPL ) get_directory_property( FILESYSTEM_IMPL DIRECTORY src/main/include DEFINITION FILESYSTEM_IMPL ) get_directory_property( STD_MAKE_UNIQUE_IMPL DIRECTORY src/main/include DEFINITION STD_MAKE_UNIQUE_IMPL ) +get_directory_property( HAS_BOOST_STACKTRACE DIRECTORY src/main/include DEFINITION HAS_BOOST_STACKTRACE ) -foreach(varName HAS_STD_LOCALE HAS_ODBC HAS_MBSRTOWCS HAS_WCSTOMBS HAS_FWIDE HAS_LIBESMTP HAS_SYSLOG HAS_FMT) +foreach(varName HAS_STD_LOCALE HAS_ODBC HAS_MBSRTOWCS HAS_WCSTOMBS HAS_FWIDE HAS_LIBESMTP HAS_SYSLOG HAS_FMT HAS_BOOST_STACKTRACE) if(${varName} EQUAL 0) set(${varName} "OFF" ) elseif(${varName} EQUAL 1) @@ -278,6 +279,7 @@ message(STATUS " shared_mutex implementation ..... : ${SHARED_MUTEX_IMPL}") message(STATUS " atomic implementation ........... : ${ATOMIC_IMPL}") message(STATUS " filesystem implementation ....... : ${FILESYSTEM_IMPL}") message(STATUS " std::make_unique found? ......... : ${STD_MAKE_UNIQUE_IMPL}") +message(STATUS " Boost stacktrace support ........ : ${HAS_BOOST_STACKTRACE}") if(BUILD_TESTING) message(STATUS "Applications required for tests:") diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt index acd4f46a..59276e19 100644 --- a/src/main/cpp/CMakeLists.txt +++ b/src/main/cpp/CMakeLists.txt @@ -175,6 +175,7 @@ target_sources(log4cxx simplelayout.cpp sizebasedtriggeringpolicy.cpp smtpappender.cpp + stacktracepatternconverter.cpp strftimedateformat.cpp stringhelper.cpp stringmatchfilter.cpp diff --git a/src/main/cpp/loggingevent.cpp b/src/main/cpp/loggingevent.cpp index adba3c43..0b1f1930 100644 --- a/src/main/cpp/loggingevent.cpp +++ b/src/main/cpp/loggingevent.cpp @@ -39,6 +39,10 @@ #include <log4cxx/private/log4cxx_private.h> #include <log4cxx/helpers/date.h> +#if LOG4CXX_HAS_BOOST_STACKTRACE +#include <boost/stacktrace.hpp> +#endif + using namespace log4cxx; using namespace log4cxx::spi; using namespace log4cxx::helpers; @@ -142,6 +146,10 @@ struct LoggingEvent::LoggingEventPrivate const LogString& threadUserName; std::chrono::time_point<std::chrono::system_clock> chronoTimeStamp; + +#if LOG4CXX_HAS_BOOST_STACKTRACE + boost::stacktrace::stacktrace stacktrace; +#endif }; IMPLEMENT_LOG4CXX_OBJECT(LoggingEvent) @@ -440,3 +448,12 @@ std::chrono::time_point<std::chrono::system_clock> LoggingEvent::getChronoTimeSt return m_priv->chronoTimeStamp; } +LogString LoggingEvent::getStacktrace() const{ +#if !LOG4CXX_HAS_BOOST_STACKTRACE + return LogString(); +#else + ::log4cxx::helpers::MessageBuffer oss_; + return oss_.str(oss_ << m_priv->stacktrace); +#endif +} + diff --git a/src/main/cpp/patternlayout.cpp b/src/main/cpp/patternlayout.cpp index b2f6c56b..8fae6bd3 100644 --- a/src/main/cpp/patternlayout.cpp +++ b/src/main/cpp/patternlayout.cpp @@ -47,6 +47,7 @@ #include <log4cxx/pattern/propertiespatternconverter.h> #include <log4cxx/pattern/throwableinformationpatternconverter.h> #include <log4cxx/pattern/threadusernamepatternconverter.h> +#include <log4cxx/pattern/stacktracepatternconverter.h> using namespace log4cxx; @@ -256,6 +257,8 @@ log4cxx::pattern::PatternMap PatternLayout::getFormatSpecifiers() RULES_PUT("properties", PropertiesPatternConverter); RULES_PUT("throwable", ThrowableInformationPatternConverter); + + RULES_PUT("st", StacktracePatternConverter); return specs; } diff --git a/src/main/cpp/stacktracepatternconverter.cpp b/src/main/cpp/stacktracepatternconverter.cpp new file mode 100644 index 00000000..5fb71db4 --- /dev/null +++ b/src/main/cpp/stacktracepatternconverter.cpp @@ -0,0 +1,50 @@ +/* + * 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/logstring.h> +#include <log4cxx/pattern/stacktracepatternconverter.h> +#include <log4cxx/spi/loggingevent.h> +#include <log4cxx/helpers/loglog.h> + +using namespace log4cxx; +using namespace log4cxx::pattern; +using namespace log4cxx::spi; +using namespace log4cxx::helpers; + +IMPLEMENT_LOG4CXX_OBJECT(StacktracePatternConverter) + +StacktracePatternConverter::StacktracePatternConverter() : + LoggingEventPatternConverter(LOG4CXX_STR("Stacktrace"), + LOG4CXX_STR("stacktrace")) +{ +} + +PatternConverterPtr StacktracePatternConverter::newInstance( + const std::vector<LogString>& /* options */) +{ + static PatternConverterPtr def = std::make_shared<StacktracePatternConverter>(); + return def; +} + +void StacktracePatternConverter::format( + const LoggingEventPtr& event, + LogString& toAppendTo, + Pool& /* p */) const +{ + toAppendTo.append(event->getStacktrace()); +} + diff --git a/src/main/include/CMakeLists.txt b/src/main/include/CMakeLists.txt index 3b235249..4d0ee04f 100644 --- a/src/main/include/CMakeLists.txt +++ b/src/main/include/CMakeLists.txt @@ -240,6 +240,13 @@ else() set(STD_MAKE_UNIQUE_FOUND 0) endif() +find_package(Boost COMPONENTS stacktrace) +if(${Boost_FOUND}) + set(HAS_BOOST_STACKTRACE 1) +else() + set(HAS_BOOST_STACKTRACE 0) +endif() + # Configure both our private header and our public header configure_file(${CMAKE_CURRENT_SOURCE_DIR}/log4cxx/private/log4cxx_private.h.in ${CMAKE_CURRENT_BINARY_DIR}/log4cxx/private/log4cxx_private.h diff --git a/src/main/include/log4cxx/pattern/stacktracepatternconverter.h b/src/main/include/log4cxx/pattern/stacktracepatternconverter.h new file mode 100644 index 00000000..019dcd2d --- /dev/null +++ b/src/main/include/log4cxx/pattern/stacktracepatternconverter.h @@ -0,0 +1,62 @@ +/* + * 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_STACKTRACE_PATTERN_CONVERTER +#define _LOG4CXX_STACKTRACE_PATTERN_CONVERTER + +#include <log4cxx/pattern/loggingeventpatternconverter.h> + +namespace log4cxx +{ +namespace pattern +{ + + +/** + * Formats the message of an logging event. + * + * + * + */ +class LOG4CXX_EXPORT StacktracePatternConverter : public LoggingEventPatternConverter +{ + public: + DECLARE_LOG4CXX_PATTERN(StacktracePatternConverter) + BEGIN_LOG4CXX_CAST_MAP() + LOG4CXX_CAST_ENTRY(StacktracePatternConverter) + LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter) + END_LOG4CXX_CAST_MAP() + + StacktracePatternConverter(); + + /** + * Obtains an instance of pattern converter. + * @param options options, may be null. + * @return instance of pattern converter. + */ + static PatternConverterPtr newInstance( + const std::vector<LogString>& options); + + using LoggingEventPatternConverter::format; + + void format(const spi::LoggingEventPtr& event, + LogString& toAppendTo, + helpers::Pool& p) const override; +}; +} +} +#endif diff --git a/src/main/include/log4cxx/patternlayout.h b/src/main/include/log4cxx/patternlayout.h index 3aa1f748..fdb4fb35 100644 --- a/src/main/include/log4cxx/patternlayout.h +++ b/src/main/include/log4cxx/patternlayout.h @@ -248,6 +248,15 @@ LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr); * </td> * </tr> * <tr> + * <td align="center"><strong>st</strong></td> + * <td> + * Print the stacktrace(if available). Requires Log4cxx to have been built with Boost + * stacktrace support. + * + * If no stacktrace is available, does not print anything. + * </td> + * </tr> + * <tr> * <td align="center"><strong>%</strong></td> * <td>The sequence %% outputs a single percent sign.</td> * </tr> diff --git a/src/main/include/log4cxx/private/log4cxx_private.h.in b/src/main/include/log4cxx/private/log4cxx_private.h.in index 9eb5ec23..b6ad1bdb 100644 --- a/src/main/include/log4cxx/private/log4cxx_private.h.in +++ b/src/main/include/log4cxx/private/log4cxx_private.h.in @@ -63,5 +63,6 @@ #define LOG4CXX_HAS_SETTHREADDESCRIPTION @HAS_SETTHREADDESCRIPTION@ #define LOG4CXX_HAS_GETTHREADDESCRIPTION @HAS_GETTHREADDESCRIPTION@ #define LOG4CXX_HAS_THREAD_LOCAL @HAS_THREAD_LOCAL@ +#define LOG4CXX_HAS_BOOST_STACKTRACE @HAS_BOOST_STACKTRACE@ #endif diff --git a/src/main/include/log4cxx/spi/loggingevent.h b/src/main/include/log4cxx/spi/loggingevent.h index 8641fcf6..1e14764b 100644 --- a/src/main/include/log4cxx/spi/loggingevent.h +++ b/src/main/include/log4cxx/spi/loggingevent.h @@ -177,6 +177,15 @@ class LOG4CXX_EXPORT LoggingEvent : */ void setProperty(const LogString& key, const LogString& value); + /** + * Returns a string of the backtrace. Note that the backtrace is created inside + * of the LoggingEvent, and as such will likely be several levels deeper than the line + * of code that generated the logging event. + * + * @return A backtrace string, or nothing if backtrace support is not available. + */ + LogString getStacktrace() const; + private: LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(LoggingEventPrivate, m_priv)
