You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rm...@apache.org on 2022/12/10 02:09:33 UTC

[logging-log4cxx] 01/01: LOGCXX-567 Add optional stacktrace support

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 <ro...@rm5248.com>
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)