在多进程使用log4cplus同时向一个日志文件写的时候,官方的FAQ建议使用SoskcetAppender, 即以server client模式来写日志,保证写日志同步。
写了一个小程序,fork出一个server进程,和5个client进程来写日志,当日志大小到达4G的时候做切割。
/*
* =====================================================================================
*
* Filename: multiprocesslog.cpp
*
* Description:
*
* Version: 1.0
* Created: 11/15/2011 02:48:44 PM
* Revision: none
* Compiler: gcc
*
* Author: Xu Zhe Ming,
* Company:
*
* =====================================================================================
*/
#include <log4cplus/fileappender.h>
#include <log4cplus/socketappender.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/layout.h>
#include <time.h>
#include <log4cplus/configurator.h>
#include <iomanip>
#include <log4cplus/logger.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/helpers/socket.h>
#include <stdio.h>
#include <string>
using namespace log4cplus;
using namespace std;
using namespace log4cplus::helpers;
//server端
int log_server(int port)
{
//创建一个socket,绑定端口
helpers::ServerSocket serverSocket(port);
Logger debug_logger;
Logger info_logger;
//注意int会溢出
long log_size = long(1024) * 1024 * 1024 * 4;
//初始化一个debug logger,并绑定到一个文件
{
SharedAppenderPtr pFileAppender_normal(new RollingFileAppender(("log_file_debug") , log_size, 10));
debug_logger = Logger::getInstance("debug_logger");
debug_logger.addAppender(pFileAppender_normal);
}
//初始化一个info logger,并绑定到一个文件
{
SharedAppenderPtr pFileAppender_normal(new RollingFileAppender(("log_file_info") , log_size, 10));
info_logger = Logger::getInstance("info_logger");
info_logger.addAppender(pFileAppender_normal);
}
//初始化其他的logger,如warn, error, fatal
//...
while(1)
{
//accept
helpers::Socket clientsock = serverSocket.accept();
SocketBuffer msgSizeBuffer(sizeof(unsigned int));
if(!clientsock.read(msgSizeBuffer))
{
return 0;
}
unsigned int msgSize = msgSizeBuffer.readInt();
SocketBuffer buffer(msgSize);
//读取日志消息到buffer
if(!clientsock.read(buffer))
{
return 0;
}
//转化成event
spi::InternalLoggingEvent event = readFromBuffer(buffer);
int level = event.getLogLevel();
//判断日志的level
if(level == DEBUG_LOG_LEVEL)
{
debug_logger.callAppenders(event);
}
else if(level == INFO_LOG_LEVEL)
{
info_logger.callAppenders(event);
}
//...
}
return 0;
}
//client端
int log_client(string server_ip, int server_port)
{
SharedAppenderPtr _append(new SocketAppender(server_ip, server_port, "ServerName"));
Logger::getRoot().addAppender(_append);
while(1)
{
int rand_num = rand();
int remainder = rand_num % 2;
if (remainder == 0)
LOG4CPLUS_INFO(Logger::getRoot(), "client logging event number ... ");
else
LOG4CPLUS_DEBUG(Logger::getRoot(), "client logging odd number... ");
//sleep(1);
}
}
int main()
{
pid_t pid = fork();
//child, let's run a log server process
if(pid == 0)
{
log_server(20000);
}
//parent, let's fork some more processes to write logs
else
{
for(int i = 0; i < 5; i++)
{
pid = fork();
//child, let's run a log client process
if(pid == 0)
{
log_client("localhost", 20000);
}
}
}
while(1)
{
sleep(1);
}
return 0;
}