Euphoria Audio, LLC

Audio, Video and Data Consulting

Log4cxx XML Configuration Location Patch

No Comments »

I've been working in C and C++ quite a bit lately and using the Apache Log4cxx library for file and syslogging. It works wonderfully but I didn't like the fact that it required it's own configuration file (unless you set it up programmatically). My configs are in XML and I used Log4cxx's XML configuration as well. Since it's silly to distribute two configs for each application, I wrote the patch below that lets you put the Log4cxx configuraton root anywhere within your own XML file. I submitted it to the Apache dev list back in January but it doesn't look like anyone's comitting to the project so I'll post it here in the hopes that someone finds it useful.

Index: src/main/cpp/domconfigurator.cpp
===================================================================
--- src/main/cpp/domconfigurator.cpp	(revision 1061597)
+++ src/main/cpp/domconfigurator.cpp	(working copy)
@@ -742,7 +742,12 @@
             } else {
                 AppenderMap appenders;
                 CharsetDecoderPtr utf8Decoder(CharsetDecoder::getUTF8Decoder());
-                parse(p, utf8Decoder, doc->root, doc, appenders);
+				int found_root = 0;
+				//LogLog::error(LOG4CXX_STR("Calling parse ") + filename.getPath() + LOG4CXX_STR("..."));
+                parse(p, utf8Decoder, doc->root, doc, appenders, found_root);
+				if (found_root < 1){
+					LogLog::error(LOG4CXX_STR("Could not find root  element."));
+				}
             }
         }
 }
@@ -863,25 +868,26 @@
                             log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
                             apr_xml_elem* element,
                             apr_xml_doc* doc,
-                            AppenderMap& appenders)
+                            AppenderMap& appenders,
+							int &found_root)
 {
     std::string rootElementName(element->name);

-    if (rootElementName != CONFIGURATION_TAG)
-        {
-                if(rootElementName == OLD_CONFIGURATION_TAG)
-                {
-                        //LogLog::warn(LOG4CXX_STR("The <")+String(OLD_CONFIGURATION_TAG)+
-                        // LOG4CXX_STR("> element has been deprecated."));
-                        //LogLog::warn(LOG4CXX_STR("Use the <")+String(CONFIGURATION_TAG)+
-                        // LOG4CXX_STR("> element instead."));
-                }
-                else
-                {
-                        LogLog::error(LOG4CXX_STR("DOM element is - not a  element."));
-                        return;
-                }
-    }
+    if (rootElementName != CONFIGURATION_TAG && rootElementName != OLD_CONFIGURATION_TAG)
+    {
+		// keep parsing till we find a root tag
+		if (!found_root && element->first_child){
+			apr_xml_elem *ce = element->first_child;
+			while (ce){
+				parse(p, utf8Decoder, ce, doc, appenders, found_root);
+				if (found_root)
+					break;
+				ce = ce->next;
+			}
+		}
+	}else
+		found_root = 1;
+	

     LogString debugAttrib = subst(getAttribute(utf8Decoder, element, INTERNAL_DEBUG_ATTR));

Index: src/main/include/log4cxx/xml/domconfigurator.h
===================================================================
--- src/main/include/log4cxx/xml/domconfigurator.h	(revision 1061597)
+++ src/main/include/log4cxx/xml/domconfigurator.h	(working copy)
@@ -206,7 +206,8 @@
                             log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
                             apr_xml_elem* element,
                             apr_xml_doc* doc,
-                            AppenderMap& appenders);
+                            AppenderMap& appenders,
+                            int &found_root);

                 public:
                         DOMConfigurator();

An example XML file that includes a Log4cxx configuration looks like this:

	<?xml version="1.0" encoding="utf-8"?>

	<MyApp>

	  <AppVar1>Hello</AppVar1>

	  <AppVar2>World</AppVar2>

	 

	<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	     <appender name="Console" class="org.apache.log4j.ConsoleAppender">

	         <param name="Target" value="System.out"/>

	         <layout class="org.apache.log4j.PatternLayout">

	             <param name="ConversionPattern" value="%-5p [%M{1}] %m%n"/>

	         </layout>

	     </appender>

	    <appender name="AppLog" class="org.apache.log4j.rolling.RollingFileAppender">

	          <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">

	             <param name="FileNamePattern" value="/var/log/MyApp.%i"/>

	             <param name="MinIndex" value="0"/>

	             <param name="MaxIndex" value="2"/>

	         </rollingPolicy>

	         <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">

	            <param name="maxFileSize" value="25MB"/>

	         </triggeringPolicy>

	         <layout class="org.apache.log4j.PatternLayout">

	             <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%p] [%M] (%F:%L) %m%n"/>

	         </layout>

	     </appender>

	 

	  <appender name="MySyslog" class="org.apache.log4j.net.SyslogAppender">

	     <param name="Facility" value="LOCAL7"/>

	     <param name="FacilityPrinting" value="true"/>

	     <param name="SyslogHost" value="127.0.0.1"/>  

	     <layout class="org.apache.log4j.PatternLayout">

	       <param name="ConversionPattern" value="%d{MMM d HH:mm:ss} %m"/>

	     </layout>

	   </appender>

	     <root>

	         <priority value="TRACE" />

	         <appender-ref ref="AppLog"/>

	         <appender-ref ref="Console"/>

	     </root>

	     <category name="MySyslogger" additivity="false">

	    <priority value ="ALL" />

	    <appender-ref ref="MySyslog" />

	     </category>

	 </log4j:configuration>

	</MyApp>

 

Leave a Reply