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/03/19 16:32:52 UTC

[logging-log4cxx] branch LOGCXX-550 created (now 7b693b9)

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

rmiddleton pushed a change to branch LOGCXX-550
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git.


      at 7b693b9  LOGCXX-550 The thread name should now be able to be logged

This branch includes the following new commits:

     new 7b693b9  LOGCXX-550 The thread name should now be able to be logged

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[logging-log4cxx] 01/01: LOGCXX-550 The thread name should now be able to be logged

Posted by rm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7b693b91d5876704132a76ce52b84d7a2d6003e7
Author: Robert Middleton <ro...@rm5248.com>
AuthorDate: Sat Mar 19 12:32:33 2022 -0400

    LOGCXX-550 The thread name should now be able to be logged
---
 src/cmake/pthread/log4cxx-pthread.cmake            |  6 ++-
 src/cmake/pthread/test-pthread-getname.cpp         |  7 +++
 .../{test-pthread.cpp => test-pthread-setname.cpp} |  0
 src/main/cpp/CMakeLists.txt                        |  1 +
 src/main/cpp/loggingevent.cpp                      | 37 ++++++++++++++-
 src/main/cpp/patternlayout.cpp                     |  4 ++
 src/main/cpp/threadusernamepatternconverter.cpp    | 53 ++++++++++++++++++++++
 src/main/include/CMakeLists.txt                    |  6 ++-
 .../pattern/threadusernamepatternconverter.h       | 53 ++++++++++++++++++++++
 src/main/include/log4cxx/patternlayout.h           |  8 +++-
 .../include/log4cxx/private/log4cxx_private.h.in   |  2 +
 src/main/include/log4cxx/spi/loggingevent.h        | 16 +++++++
 src/test/cpp/pattern/patternparsertestcase.cpp     | 41 +++++++++++++++++
 13 files changed, 229 insertions(+), 5 deletions(-)

diff --git a/src/cmake/pthread/log4cxx-pthread.cmake b/src/cmake/pthread/log4cxx-pthread.cmake
index d4a5272..bd9e859 100644
--- a/src/cmake/pthread/log4cxx-pthread.cmake
+++ b/src/cmake/pthread/log4cxx-pthread.cmake
@@ -1,6 +1,10 @@
 include(FindThreads)
 
 try_compile(PTHREAD_SETNAME_NP_FOUND "${CMAKE_BINARY_DIR}/pthread-compile-tests"
-    "${CMAKE_CURRENT_LIST_DIR}/test-pthread.cpp"
+    "${CMAKE_CURRENT_LIST_DIR}/test-pthread-setname.cpp"
+    LINK_LIBRARIES Threads::Threads )
+
+try_compile(PTHREAD_GETNAME_NP_FOUND "${CMAKE_BINARY_DIR}/pthread-compile-tests"
+    "${CMAKE_CURRENT_LIST_DIR}/test-pthread-getname.cpp"
     LINK_LIBRARIES Threads::Threads )
 
diff --git a/src/cmake/pthread/test-pthread-getname.cpp b/src/cmake/pthread/test-pthread-getname.cpp
new file mode 100644
index 0000000..4e149ed
--- /dev/null
+++ b/src/cmake/pthread/test-pthread-getname.cpp
@@ -0,0 +1,7 @@
+#include <pthread.h>
+
+int main(){
+	pthread_t tid;
+	char buffer[16];
+	pthread_getname_np(tid, buffer, sizeof(buffer));
+}
diff --git a/src/cmake/pthread/test-pthread.cpp b/src/cmake/pthread/test-pthread-setname.cpp
similarity index 100%
rename from src/cmake/pthread/test-pthread.cpp
rename to src/cmake/pthread/test-pthread-setname.cpp
diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index 419503b..bb1445a 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -165,6 +165,7 @@ target_sources(log4cxx
   telnetappender.cpp
   threadlocal.cpp
   threadpatternconverter.cpp
+  threadusernamepatternconverter.cpp
   threadspecificdata.cpp
   threadutility.cpp
   throwableinformationpatternconverter.cpp
diff --git a/src/main/cpp/loggingevent.cpp b/src/main/cpp/loggingevent.cpp
index 98056d5..5fcba0e 100644
--- a/src/main/cpp/loggingevent.cpp
+++ b/src/main/cpp/loggingevent.cpp
@@ -77,7 +77,8 @@ LoggingEvent::LoggingEvent(
 	message(message1),
 	timeStamp(apr_time_now()),
 	locationInfo(locationInfo1),
-	threadName(getCurrentThreadName())
+	threadName(getCurrentThreadName()),
+	threadUserName(getCurrentThreadUserName())
 {
 }
 
@@ -88,6 +89,10 @@ LoggingEvent::~LoggingEvent()
 	delete properties;
 }
 
+const LogString& LoggingEvent::getThreadUserName() const{
+	return threadUserName;
+}
+
 bool LoggingEvent::getNDC(LogString& dest) const
 {
 	if (ndcLookupRequired)
@@ -247,6 +252,36 @@ const LogString LoggingEvent::getCurrentThreadName()
 #endif /* APR_HAS_THREADS */
 }
 
+const LogString LoggingEvent::getCurrentThreadUserName()
+{
+	LOG4CXX_THREAD_LOCAL LogString thread_name;
+	if( thread_name.size() ){
+		return thread_name;
+	}
+
+#if LOG4CXX_HAS_PTHREAD_GETNAME
+	char result[16];
+	pthread_t current_thread = pthread_self();
+	if( pthread_getname_np( current_thread, result, sizeof(result) ) < 0 ){
+		thread_name = LOG4CXX_STR("(noname)");
+	}
+
+	log4cxx::helpers::Transcoder::decode(reinterpret_cast<const char*>(result), thread_name);
+#elif LOG4CXX_HAS_GETTHREADDESCRIPTION
+	char* result;
+	DWORD threadId = GetCurrentThreadId();
+	if( GetThreadDescription( threadId, &result ) == 0 ){
+		// Success
+		log4cxx::helpers::Transcoder::decode(reinterpret_cast<const char*>(result), thread_name);
+		LocalFree(result);
+	}else{
+		thread_name = LOG4CXX_STR("(noname)");
+	}
+#else
+	thread_name = LOG4CXX_STR("(noname)");
+#endif
+	return thread_name;
+}
 
 void LoggingEvent::setProperty(const LogString& key, const LogString& value)
 {
diff --git a/src/main/cpp/patternlayout.cpp b/src/main/cpp/patternlayout.cpp
index 3070085..4b610db 100644
--- a/src/main/cpp/patternlayout.cpp
+++ b/src/main/cpp/patternlayout.cpp
@@ -49,6 +49,7 @@
 #include <log4cxx/pattern/ndcpatternconverter.h>
 #include <log4cxx/pattern/propertiespatternconverter.h>
 #include <log4cxx/pattern/throwableinformationpatternconverter.h>
+#include <log4cxx/pattern/threadusernamepatternconverter.h>
 
 
 using namespace log4cxx;
@@ -190,6 +191,9 @@ log4cxx::pattern::PatternMap PatternLayout::getFormatSpecifiers()
 	RULES_PUT("t", ThreadPatternConverter);
 	RULES_PUT("thread", ThreadPatternConverter);
 
+	RULES_PUT("T", ThreadUsernamePatternConverter);
+	RULES_PUT("threadname", ThreadUsernamePatternConverter);
+
 	RULES_PUT("x", NDCPatternConverter);
 	RULES_PUT("ndc", NDCPatternConverter);
 
diff --git a/src/main/cpp/threadusernamepatternconverter.cpp b/src/main/cpp/threadusernamepatternconverter.cpp
new file mode 100644
index 0000000..81e042a
--- /dev/null
+++ b/src/main/cpp/threadusernamepatternconverter.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+#if defined(_MSC_VER)
+	#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/threadusernamepatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ThreadUsernamePatternConverter)
+
+ThreadUsernamePatternConverter::ThreadUsernamePatternConverter() :
+	LoggingEventPatternConverter(LOG4CXX_STR("Thread Name"),
+		LOG4CXX_STR("Thread Name"))
+{
+}
+
+PatternConverterPtr ThreadUsernamePatternConverter::newInstance(
+	const std::vector<LogString>& /* options */)
+{
+	static PatternConverterPtr def(new ThreadUsernamePatternConverter());
+	return def;
+}
+
+void ThreadUsernamePatternConverter::format(
+	const LoggingEventPtr& event,
+	LogString& toAppendTo,
+	Pool& /* p */) const
+{
+	toAppendTo.append(event->getThreadUserName());
+}
+
diff --git a/src/main/include/CMakeLists.txt b/src/main/include/CMakeLists.txt
index 667d78a..e7dddd0 100644
--- a/src/main/include/CMakeLists.txt
+++ b/src/main/include/CMakeLists.txt
@@ -115,13 +115,17 @@ if(UNIX)
     if(${PTHREAD_SETNAME_NP_FOUND})
 	set(HAS_PTHREAD_SETNAME 1)
     endif()
+    if(${PTHREAD_GETNAME_NP_FOUND})
+	set(HAS_PTHREAD_GETNAME 1)
+    endif()
 endif(UNIX)
 
 if(WIN32)
     CHECK_SYMBOL_EXISTS(SetThreadDescription "windows.h;processthreadsapi.h" HAS_SETTHREADDESCRIPTION)
+    CHECK_SYMBOL_EXISTS(GetThreadDescription "windows.h;processthreadsapi.h" HAS_GETTHREADDESCRIPTION)
 endif(WIN32)
 
-foreach(varName HAS_STD_LOCALE  HAS_ODBC  HAS_MBSRTOWCS  HAS_WCSTOMBS  HAS_FWIDE  HAS_LIBESMTP  HAS_SYSLOG HAS_PTHREAD_SIGMASK HAS_PTHREAD_SETNAME HAS_SETTHREADDESCRIPTION)
+foreach(varName HAS_STD_LOCALE  HAS_ODBC  HAS_MBSRTOWCS  HAS_WCSTOMBS  HAS_FWIDE  HAS_LIBESMTP  HAS_SYSLOG HAS_PTHREAD_SIGMASK HAS_PTHREAD_SETNAME HAS_SETTHREADDESCRIPTION HAS_GETTHREADDESCRIPTION)
   if(${varName} EQUAL 0)
     continue()
   elseif(${varName} EQUAL 1)
diff --git a/src/main/include/log4cxx/pattern/threadusernamepatternconverter.h b/src/main/include/log4cxx/pattern/threadusernamepatternconverter.h
new file mode 100644
index 0000000..60bb9ca
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/threadusernamepatternconverter.h
@@ -0,0 +1,53 @@
+/*
+ * 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_THREAD_USERNAME_PATTERN_CONVERTER_H
+#define LOG4CXX_THREAD_USERNAME_PATTERN_CONVERTER_H
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx
+{
+
+namespace pattern
+{
+
+class LOG4CXX_EXPORT ThreadUsernamePatternConverter : public LoggingEventPatternConverter
+{
+        ThreadUsernamePatternConverter();
+
+    public:
+	    DECLARE_LOG4CXX_PATTERN(ThreadUsernamePatternConverter)
+	    BEGIN_LOG4CXX_CAST_MAP()
+	    LOG4CXX_CAST_ENTRY(ThreadUsernamePatternConverter)
+	    LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+	    END_LOG4CXX_CAST_MAP()
+
+	    static PatternConverterPtr newInstance(
+	            const std::vector<LogString>& options);
+
+	    void format(const log4cxx::spi::LoggingEventPtr& event,
+	            LogString& toAppendTo,
+	            log4cxx::helpers::Pool& p) const;
+};
+
+}
+}
+
+#endif
+
diff --git a/src/main/include/log4cxx/patternlayout.h b/src/main/include/log4cxx/patternlayout.h
index 7b695d7..aa59b3b 100644
--- a/src/main/include/log4cxx/patternlayout.h
+++ b/src/main/include/log4cxx/patternlayout.h
@@ -206,8 +206,12 @@ LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr);
  *      </td>
  *  </tr>
  *  <tr>
- *      <td align="center"><strong>t</strong></td>
- *      <td>Used to output the name of the thread that generated the logging event.</td>
+ *      <td align="center"><strong>t</strong><p><strong>thread</strong></p></td>
+ *      <td>Used to output the ID of the thread that generated the logging event.</td>
+ *  </tr>
+ *  <tr>
+ *      <td align="center"><strong>T</strong><p><strong>threadname</strong></p></td>
+ *      <td>Used to output the name of the thread that generated the logging event.  May not be available on all platforms.</td>
  *  </tr>
  *  <tr>
  *      <td align="center"><strong>x</strong></td>
diff --git a/src/main/include/log4cxx/private/log4cxx_private.h.in b/src/main/include/log4cxx/private/log4cxx_private.h.in
index bf965c9..26281e0 100644
--- a/src/main/include/log4cxx/private/log4cxx_private.h.in
+++ b/src/main/include/log4cxx/private/log4cxx_private.h.in
@@ -55,7 +55,9 @@
 
 #define LOG4CXX_HAS_PTHREAD_SIGMASK @HAS_PTHREAD_SIGMASK@
 #define LOG4CXX_HAS_PTHREAD_SETNAME @HAS_PTHREAD_SETNAME@
+#define LOG4CXX_HAS_PTHREAD_GETNAME @HAS_PTHREAD_GETNAME@
 #define LOG4CXX_HAS_SETTHREADDESCRIPTION @HAS_SETTHREADDESCRIPTION@
+#define LOG4CXX_HAS_GETTHREADDESCRIPTION @HAS_GETTHREADDESCRIPTION@
 
 #ifdef __BORLANDC__
 /*
diff --git a/src/main/include/log4cxx/spi/loggingevent.h b/src/main/include/log4cxx/spi/loggingevent.h
index 6e40103..ffea0d4 100644
--- a/src/main/include/log4cxx/spi/loggingevent.h
+++ b/src/main/include/log4cxx/spi/loggingevent.h
@@ -117,6 +117,12 @@ class LOG4CXX_EXPORT LoggingEvent :
 			return threadName;
 		}
 
+		/**
+		 * Get the user name of the thread.  The default name is (noname) if
+		 * Log4cxx is unable to retrieve the name using a platform-specific call.
+		 */
+		const LogString& getThreadUserName() const;
+
 		/** The number of microseconds elapsed from 01.01.1970 until logging event
 		 was created. */
 		inline log4cxx_time_t getTimeStamp() const
@@ -248,15 +254,25 @@ class LOG4CXX_EXPORT LoggingEvent :
 
 		/** The identifier of thread in which this logging event
 		was generated.
+		Note: This is the thread ID in hex.
+		See also LoggingEvent::threadUserName
 		*/
 		const LogString threadName;
 
+		/**
+		 * The user-specified name of the thread(on a per-platform basis).
+		 * This is set using a method such as pthread_setname_np on POSIX
+		 * systems or SetThreadDescription on Windows.
+		 */
+		const LogString threadUserName;
+
 		//
 		//   prevent copy and assignment
 		//
 		LoggingEvent(const LoggingEvent&);
 		LoggingEvent& operator=(const LoggingEvent&);
 		static const LogString getCurrentThreadName();
+		static const LogString getCurrentThreadUserName();
 
 		static void writeProlog(log4cxx::helpers::ObjectOutputStream& os, log4cxx::helpers::Pool& p);
 
diff --git a/src/test/cpp/pattern/patternparsertestcase.cpp b/src/test/cpp/pattern/patternparsertestcase.cpp
index 01a7a42..a8ea26c 100644
--- a/src/test/cpp/pattern/patternparsertestcase.cpp
+++ b/src/test/cpp/pattern/patternparsertestcase.cpp
@@ -50,6 +50,11 @@
 #include <log4cxx/pattern/ndcpatternconverter.h>
 #include <log4cxx/pattern/propertiespatternconverter.h>
 #include <log4cxx/pattern/throwableinformationpatternconverter.h>
+#include <log4cxx/pattern/threadusernamepatternconverter.h>
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+#include <thread>
 
 
 using namespace log4cxx;
@@ -71,6 +76,7 @@ LOGUNIT_CLASS(PatternParserTestCase)
 	LOGUNIT_TEST(testBasic1);
 	LOGUNIT_TEST(testBasic2);
 	LOGUNIT_TEST(testMultiOption);
+	LOGUNIT_TEST(testThreadUsername);
 	LOGUNIT_TEST_SUITE_END();
 
 	LoggingEventPtr event;
@@ -78,6 +84,21 @@ LOGUNIT_CLASS(PatternParserTestCase)
 public:
 	void setUp()
 	{
+		LogString threadName = "log4cxx-thr";
+
+#if LOG4CXX_HAS_PTHREAD_SETNAME
+	if( pthread_setname_np( pthread_self(), threadName.c_str() ) < 0 ){
+		LOGLOG_ERROR( LOG4CXX_STR("unable to set thread name") );
+	}
+#elif LOG4CXX_HAS_SETTHREADDESCRIPTION
+	HRESULT hr = SetThreadDescription(GetCurrentThread(), threadName.c_str());
+	if(FAILED(hr)){
+		LOGLOG_ERROR( LOG4CXX_STR("unable to set thread name") );
+	}
+#else
+		threadName = LOG4CXX_STR("(noname)");
+#endif
+
 		event = LoggingEventPtr(new LoggingEvent(
 					LOG4CXX_STR("org.foobar"), Level::getInfo(), LOG4CXX_STR("msg 1"), LOG4CXX_LOCATION));
 	}
@@ -124,6 +145,9 @@ public:
 		RULES_PUT("t", ThreadPatternConverter);
 		RULES_PUT("thread", ThreadPatternConverter);
 
+		RULES_PUT("T", ThreadUsernamePatternConverter);
+		RULES_PUT("threadname", ThreadUsernamePatternConverter);
+
 		RULES_PUT("x", NDCPatternConverter);
 		RULES_PUT("ndc", NDCPatternConverter);
 
@@ -243,6 +267,23 @@ public:
 			expected);
 	}
 
+	void testThreadUsername()
+	{
+		Pool pool;
+		RelativeTimeDateFormat relativeFormat;
+		LogString expected;
+		relativeFormat.format(expected, event->getTimeStamp(), pool);
+
+		expected.append(LOG4CXX_STR(" INFO  ["));
+		expected.append(event->getThreadUserName());
+		expected.append(LOG4CXX_STR("] org.foobar - msg 1"));
+		expected.append(LOG4CXX_EOL);
+
+		assertFormattedEquals(LOG4CXX_STR("%relative %-5level [%threadname] %logger - %m%n"),
+			getFormatSpecifiers(),
+			expected);
+	}
+
 };
 
 //