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 2022/12/12 08:03:15 UTC

[logging-log4cxx] 01/01: Change usage configuration documentation to be compatible with automatic configuration

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

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

commit 29a8be838097274e3ffc591a1d908cf5848e7eee
Author: Stephen Webb <st...@sabreautonomous.com.au>
AuthorDate: Mon Dec 12 19:02:45 2022 +1100

    Change usage configuration documentation to be compatible with automatic configuration
---
 src/examples/cpp/UserLib/logmanager.cpp |  71 +++++------
 src/examples/cpp/UserLib/logmanager.h   |   3 +-
 src/examples/cpp/auto-configured.cpp    |   3 +-
 src/site/markdown/usage.md              | 206 +++++++++++++++++---------------
 4 files changed, 146 insertions(+), 137 deletions(-)

diff --git a/src/examples/cpp/UserLib/logmanager.cpp b/src/examples/cpp/UserLib/logmanager.cpp
index 9c39ffb9..5b7a8bef 100644
--- a/src/examples/cpp/UserLib/logmanager.cpp
+++ b/src/examples/cpp/UserLib/logmanager.cpp
@@ -39,8 +39,7 @@ using namespace log4cxx;
 
 // Get a list of file base names that may contain configuration data
 // and put an alternate path into \c altPrefix
-	std::vector<std::string>
-DefaultConfigurationFileNames(std::string& altPrefix)
+auto DefaultConfigurationFileNames(std::string& altPrefix) -> std::vector<std::string>
 {
 	std::vector<std::string> result;
 
@@ -114,59 +113,61 @@ DefaultConfigurationFileNames(std::string& altPrefix)
 	return result;
 }
 
-struct log4cxx_initializer
+void SelectConfigurationFile()
 {
-	log4cxx_initializer()
-	{
 #if defined(_DEBUG)
-		helpers::LogLog::setInternalDebugging(true);
+	helpers::LogLog::setInternalDebugging(true);
 #endif
-		const char* extension[] = { ".xml", ".properties", 0 };
-		std::string altPrefix;
-		log4cxx::helpers::Pool pool;
+	const char* extension[] = { ".xml", ".properties", 0 };
+	std::string altPrefix;
+	log4cxx::helpers::Pool pool;
 
-		for (auto baseName : DefaultConfigurationFileNames(altPrefix))
+	for (auto baseName : DefaultConfigurationFileNames(altPrefix))
+	{
+		int i = 0;
+		for (; extension[i]; ++i)
 		{
-			int i = 0;
-			for (; extension[i]; ++i)
+			log4cxx::File current_working_dir_candidate(baseName + extension[i]);
+			if (current_working_dir_candidate.exists(pool))
+			{
+				log4cxx::DefaultConfigurator::setConfigurationFileName(current_working_dir_candidate.getPath());
+				log4cxx::DefaultConfigurator::setConfigurationWatchSeconds(5);
+				break;
+			}
+			if (!altPrefix.empty())
 			{
-				log4cxx::File current_working_dir_candidate(baseName + extension[i]);
-				if (current_working_dir_candidate.exists(pool))
+				log4cxx::File alt_dir_candidate(altPrefix + baseName + extension[i]);
+				if (alt_dir_candidate.exists(pool))
 				{
-					log4cxx::DefaultConfigurator::setConfigurationFileName(current_working_dir_candidate.getPath());
+					log4cxx::DefaultConfigurator::setConfigurationFileName(alt_dir_candidate.getPath());
 					log4cxx::DefaultConfigurator::setConfigurationWatchSeconds(5);
 					break;
 				}
-				if (!altPrefix.empty())
-				{
-					log4cxx::File alt_dir_candidate(altPrefix + baseName + extension[i]);
-					if (alt_dir_candidate.exists(pool))
-					{
-						log4cxx::DefaultConfigurator::setConfigurationFileName(alt_dir_candidate.getPath());
-						log4cxx::DefaultConfigurator::setConfigurationWatchSeconds(5);
-						break;
-					}
-				}
 			}
-			if (extension[i]) // Found a configuration file?
-				break;
 		}
+		if (extension[i]) // Found a configuration file?
+			break;
 	}
-	~log4cxx_initializer()
-	{
-		log4cxx::LogManager::shutdown();
-	}
-};
+}
 
 } // namespace
 
 namespace UserLib
 {
 
-	log4cxx::LoggerPtr
-getLogger(const std::string& name)
+auto getLogger(const std::string& name) -> log4cxx::LoggerPtr
 {
-	static log4cxx_initializer initAndShutdown;
+	static struct log4cxx_initializer
+	{
+		log4cxx_initializer()
+		{
+			SelectConfigurationFile();
+		}
+		~log4cxx_initializer()
+		{
+			log4cxx::LogManager::shutdown();
+		}
+	} initialiser;
 	return name.empty()
 		? log4cxx::LogManager::getRootLogger()
 		: log4cxx::LogManager::getLogger(name);
diff --git a/src/examples/cpp/UserLib/logmanager.h b/src/examples/cpp/UserLib/logmanager.h
index a23d7adc..31274093 100644
--- a/src/examples/cpp/UserLib/logmanager.h
+++ b/src/examples/cpp/UserLib/logmanager.h
@@ -3,6 +3,7 @@
 namespace UserLib
 {
 
-extern log4cxx::LoggerPtr getLogger(const std::string& name = std::string());
+    extern auto
+getLogger(const std::string& name = std::string()) -> log4cxx::LoggerPtr;
 
 } // namespace UserLib
diff --git a/src/examples/cpp/auto-configured.cpp b/src/examples/cpp/auto-configured.cpp
index 93333209..27bbbb48 100644
--- a/src/examples/cpp/auto-configured.cpp
+++ b/src/examples/cpp/auto-configured.cpp
@@ -16,8 +16,7 @@
  */
 #include <UserLib/logmanager.h>
 
-	log4cxx::LoggerPtr
-rootLogger(UserLib::getLogger());
+extern auto rootLogger = UserLib::getLogger("MyApp");
 
 struct ExampleStaticData
 {
diff --git a/src/site/markdown/usage.md b/src/site/markdown/usage.md
index 42c8da71..20f855ec 100644
--- a/src/site/markdown/usage.md
+++ b/src/site/markdown/usage.md
@@ -361,78 +361,107 @@ properties (key=value) format.
 Let us give a taste of how this is done with the help of an imaginary
 application *MyApp* that uses Log4cxx. 
 
-~~~{.cpp}
+~~~{myapp.cpp}
+    #include "com/foo/config.h"
     #include "com/foo/bar.h"
-    using namespace com::foo;
-     
-    // include log4cxx header files.
-    #include "log4cxx/logger.h"
-    #include "log4cxx/basicconfigurator.h"
-    #include "log4cxx/helpers/exception.h"
-     
-    using namespace log4cxx;
-    using namespace log4cxx::helpers;
-     
-    LoggerPtr logger(Logger::getLogger("MyApp"));
-     
+
     int main(int argc, char **argv)
     {
-    	int result = EXIT_SUCCESS;
-    	try
-    	{
-    		// Set up a simple configuration that logs on the console.
-    		BasicConfigurator::configure();
-     
-    		LOG4CXX_INFO(logger, "Entering application.");
-    		Bar bar;
-    		bar.doIt();
-    		LOG4CXX_INFO(logger, "Exiting application.");
-    	}
-    	catch(Exception&)
-    	{
-    		result = EXIT_FAILURE;
-    	}
-     
-    	return result;
-    }
+        int result = EXIT_SUCCESS;
+        try
+        {
+            auto logger = com::foo::getLogger("MyApp");
+            LOG4CXX_INFO(logger, "Entering application.");
+            com::foo::Bar bar;
+            bar.doIt();
+            LOG4CXX_INFO(logger, "Exiting application.");
+        }
+        catch(std::exception&)
+        {
+            result = EXIT_FAILURE;
+        }
+        return result;
+     }
 ~~~
 
-*MyApp* begins by including Log4cxx headers. It then defines a static
-logger variable with the name *MyApp* which happens to be the fully
-qualified name of the class. 
+*MyApp* begins by including the file that defines the com::foo::getLogger() function.
+It obtains a logger named *MyApp*
+(which in this example is the fully qualified name)
+from the com::foo::getLogger() function.
 
-*MyApp* uses the *Bar* class defined in header file *com/foo/bar.h*. 
+*MyApp* uses the *com::foo::Bar* class defined in header file *com/foo/bar.h*.
 
-~~~{.cpp}
-    // file com/foo/bar.h
-    #include "log4cxx/logger.h"
-     
-    namespace com {
-    	namespace foo {
-    		class Bar {
-    			static log4cxx::LoggerPtr logger;
-     
-    			public:
-    				void doIt();
-    		};
-    	}
-    }
+~~~{com/foo/bar.h}
+    #include "com/foo/config.h"
+    namespace com { namespace foo {
+
+    class Bar {
+        static LoggerPtr m_logger;
+        public:
+            void doIt();
+    };
+
+    } } // namespace com::foo
 ~~~
 
-~~~{.cpp}
-    // file bar.cpp
+~~~{com/foo/bar.cpp}
     #include "com/foo/bar.h"
      
     using namespace com::foo;
     using namespace log4cxx;
      
-    LoggerPtr Bar::logger(Logger::getLogger("com.foo.bar"));
+    LoggerPtr Bar::m_logger(Logger::getLogger("com.foo.bar"));
      
     void Bar::doIt() {
-    	LOG4CXX_DEBUG(logger, "Did it again!");
+    	LOG4CXX_DEBUG(m_logger, "Did it again!");
     }
 ~~~
 
+The header file *com/foo/config.h* defines the com::foo::getLogger() function
+and a *LoggerPtr* type for convenience.
+
+~~~{com/foo/config.h}
+    #include <log4cxx/logger.h>
+    namespace com { namespace foo {
+
+    using LoggerPtr = log4cxx::LoggerPtr;
+    extern auto getLogger(const std::string& name = std::string()) -> LoggerPtr;
+
+    } } // namespace com::foo
+~~~
+
+The file *com/foo/config.cpp* which implements the com::foo::getLogger() function
+defines *initAndShutdown* as a *static struct* so its constructor
+is invoked on the first call to the com::foo::getLogger() function
+and its destructor is automatically called during application exit.
+
+~~~{com/foo/config.cpp}
+    #include "com/foo/config.h"
+
+    namespace com { namespace foo {
+
+    auto getLogger(const std::string& name) -> LoggerPtr
+    {
+        static struct log4cxx_initializer
+        {
+            log4cxx_initializer()
+            {
+                // Set up a simple configuration that logs on the console.
+                log4cxx::BasicConfigurator::configure();
+            }
+            ~log4cxx_initializer()
+            {
+                log4cxx::LogManager::shutdown();
+            }
+        } initAndShutdown;
+        return name.empty()
+            ? log4cxx::LogManager::getRootLogger()
+            : log4cxx::LogManager::getLogger(name);
+    }
+
+    } } // namespace com::foo
+~~~
+
 The invocation of the
 [BasicConfigurator::configure](@ref log4cxx.BasicConfigurator.configure)
 method creates a rather simple Log4cxx setup. This method is hardwired
@@ -453,60 +482,39 @@ The output of MyApp is:
 ~~~
 
 The previous example always outputs the same log information.
-Fortunately, it is easy to modify *MyApp* so that the log output can be
+Fortunately, it is easy to modify *config.cpp* so that the log output can be
 controlled at run-time. Here is a slightly modified version. 
 
 ~~~{.cpp}
-    // file MyApp2.cpp
-     
-    #include "com/foo/bar.h"
-    using namespace com::foo;
-     
-    // include log4cxx header files.
-    #include "log4cxx/logger.h"
-    #include "log4cxx/basicconfigurator.h"
-    #include "log4cxx/propertyconfigurator.h"
-    #include "log4cxx/helpers/exception.h"
-     
-    using namespace log4cxx;
-    using namespace log4cxx::helpers;
-    // Define a static logger variable so that it references the
-    // Logger instance named "MyApp".
-    LoggerPtr logger(Logger::getLogger("MyApp"));
-     
-    int main(int argc, char **argv)
+    #include "com/foo/config.h"
+
+    namespace com { namespace foo {
+
+    auto getLogger(const std::string& name) -> LoggerPtr
     {
-    	int result = EXIT_SUCCESS;
-    	try
-    	{
-    		if (argc > 1)
-    		{
-    			// BasicConfigurator replaced with PropertyConfigurator.
-    			PropertyConfigurator::configure(argv[1]);
-    		}
-    		else
-    		{
-    			BasicConfigurator::configure();
-    		}
-     
-    		LOG4CXX_INFO(logger, "Entering application.");
-    		Bar bar;
-    		bar.doIt();
-    		LOG4CXX_INFO(logger, "Exiting application.");
-    	}
-    	catch(Exception&)
-    	{
-    		result = EXIT_FAILURE;
-    	}
-     
-    	return result;
+        static struct log4cxx_initializer
+        {
+            log4cxx_initializer()
+            {
+    			PropertyConfigurator::configure("MyApp.properties");
+            }
+            ~log4cxx_initializer()
+            {
+                log4cxx::LogManager::shutdown();
+            }
+        } initAndShutdown;
+        return name.empty()
+            ? log4cxx::LogManager::getRootLogger()
+            : log4cxx::LogManager::getLogger(name);
     }
+
+    } } // namespace com::foo
 ~~~
 
-This version of *MyApp* instructs *PropertyConfigurator* to parse a
-configuration file and set up logging accordingly. 
+This version of *MyApp* instructs [PropertyConfigurator](@ref log4cxx.PropertyConfigurator.configure) to parse a
+*MyApp.properties* configuration file and set up logging accordingly. 
 
-Here is a sample configuration file that results in exactly same output
+Here is a sample *MyApp.properties* configuration file that results in exactly same output
 as the previous *BasicConfigurator* based example. 
 
 ~~~