Add process id to log file name in log4cxx

2020-03-04 10:08发布

问题:

In log4net i can easily set process id to to log file name from config easily

<appender name="LogFileAppender" 
type="log4net.Appender.RollingFileAppender,log4net">

<file type="log4net.Util.PatternString" value="Log[%processid]" />
  • Can i do the same for the log4cxx from config file?
  • If yes, how?

回答1:

According to the log4cxx documentation in order to currently do this you need to declare at least one MappedDiagnostic context.

An untested partial snippet of doing so is shown below

   #include <sys/types.h>
   #include <log4cxx/mdc.h>
   #include <iostream>
   #include <sstream>


   int main (int argc, char **argv)
   {
   //at the start of your program
   pid_t pid = getpid(); 
   pid_t tid = gettid();
   std::string pidstring;
   std::string tidstring;
   std::stringstream buffer;   
   buffer << pid << std::endl;
   pidstring = buffer.str();
   buffer.str(std::string());
   buffer << tid << std::endl;
   tidstring = buffer.str();
   buffer.str(std::string());
   MDC::put( "pid", pidstring);
   MDC::put( "tid", tidstring);
   // do actual stuff here

  return 0;   
  }

After further inspection of the log4cxx source, I realised that file doesn't take a ConversionPattern but FileNamePattern does. I believe you can only use FileNamePattern when you have use a TimeBasedRollingPolicy or FixedWindowRollingPolicy.

Now you can add the processid to the log by adding the following parameter in your appender tags in the XML configuration file.

<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
              <param name="FileNamePattern" value="MyApplication-%d{yyyy-MM-dd}- %X{pid}.log"/>
              <param name="activeFileName" value="MyApplication.log"/>
</rollingPolicy>
<param name="file" value="appxDailyLog.log"/>

or you can include it in the pattern layout by specifying the following layout tags also inside your appender tags in the XML configuration file.

 <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%X{pid} %X{tid} %d{yyyy-MM-dd HH:mm:ss,SSS}"/>
 </layout>

There is no simple way from the configuration file only to have each process append its own process to its own log like you are familiar with in log4net.

There were several log4cxx mailing list threads that mention dynamic log renaming, but all of them involved numerous changes in the C++ code and they don't do what you request.

The method they used involves having <param name="file" value="${logfilename}"/> where $logfilename is an environment variable that gets set by

std::string filename ="MyApp-";
filename.append(pidstring);
logger = Logger::getLogger("Nameoflogger");
setenv("logfile.name", "MyApp.log", 1);

calling something like the above snippet in the C++ code, each time you want the log name to change.

Other methods would involve patches to log4cxx as it currently doesn't have the functionality you need.

References

log4cxx Conversion Pattern Wiki

Short introduction to Apache log4cxx

log4cxx Tutorial

MDC log4cxx Class Reference