青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

CppExplore

一切像霧像雨又像風(fēng)

  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  29 隨筆 :: 0 文章 :: 280 評(píng)論 :: 0 Trackbacks

作者:CppExplore 網(wǎng)址:http://www.shnenglu.com/CppExplore/
log模塊是一個(gè)小模塊,卻是每個(gè)系統(tǒng)必備的模塊。優(yōu)秀的系統(tǒng)一定會(huì)有優(yōu)秀的log信息,也可以說(shuō)全面到位的log信息在一定程度上決定了一個(gè)系統(tǒng)的健壯性。在linux上,log模塊是跟蹤程序運(yùn)行,驗(yàn)證業(yè)務(wù)邏輯正確的唯一方法。
一、功能
一個(gè)優(yōu)秀的log系統(tǒng)應(yīng)該包含以下功能:
(1)支持打印到屏幕、文件、socket、syslog
(2)支持分級(jí)別打印
(3)支持分模塊打印
(4)支持多線程
(5)支持文件轉(zhuǎn)儲(chǔ):按時(shí)間、按大小。
二、使用原則
方便說(shuō)明,這里定義8個(gè)log級(jí)別:

typedef enum{
    XLOG_CRITICAL
=0x1,
    XLOG_ERROR
=0x2,
    XLOG_WARNING
=0x4,
    XLOG_NOTICE
=0x8,
    XLOG_INFO
=0x10,
    XLOG_DEBUG
=0x20,
    XLOG_TRACE
=0x40,
    XLOG_ALL
=0x80
}
XLogLevel;
使用方式舉例如下:
X_LOG(XLOG_NOTICE,"message[%s:%d]\n",char_value,int_value);

打印log的原則:
(1)重要的函數(shù)(業(yè)務(wù)處理)入口處打印XLOG_DEBUG級(jí)別log,打印出函數(shù)名稱、入口參數(shù)。
(2)函數(shù)有多個(gè)執(zhí)行支路,在異常退出函數(shù)的支路上,打印XLOG_WARNING級(jí)別log,表明退出原因。
(3)系統(tǒng)調(diào)用發(fā)生異常,甚至造成程序退出的地方,打印XLOG_ERROR級(jí)別log,表明發(fā)生該錯(cuò)誤的文件、行數(shù)、錯(cuò)誤號(hào)
(4)為所有的類對(duì)象實(shí)現(xiàn)dump方法,該方法打印該類中的所有私有屬性信息,以XLOG_NOTICE級(jí)別打印,當(dāng)類對(duì)象中含有自定義的類屬性時(shí),該類的dump中打印屬性類信息可以直接調(diào)用屬性類的dump。運(yùn)行期間,可以給用戶提供輸入接口:telnet、交互式shell命令行、或者簡(jiǎn)單的getchar,根據(jù)用戶要求,執(zhí)行頂級(jí)類對(duì)象的dump,以運(yùn)行期間查看系統(tǒng)內(nèi)所有數(shù)據(jù)的內(nèi)部信息。
(5)該系統(tǒng)與外在系統(tǒng)的交互信息,往來(lái)數(shù)據(jù)包使用XLOG_INFO級(jí)別打印。
(6)為了調(diào)試系統(tǒng),更為細(xì)微的查看系統(tǒng)的運(yùn)行狀況而加入的log,使用XLOG_TRACE級(jí)別。
三、log模塊框架
可選的開(kāi)源log很多:ace_log/Log4c/log4c**/log4c++/Pantheios/Log4cplus。依據(jù)開(kāi)源項(xiàng)目活躍程度、庫(kù)本身的獨(dú)立性以及參考文檔的數(shù)量,個(gè)人選擇的開(kāi)源庫(kù)是Log4cplus。個(gè)人測(cè)試,未發(fā)現(xiàn)該庫(kù)(v1.02)有bug或者內(nèi)存泄漏現(xiàn)象,大力推薦。網(wǎng)上有關(guān)該庫(kù)的文檔的也相當(dāng)多,我就不再羅唆了。
下面是我的log框架,不依賴于具體的log模塊,相信你會(huì)喜歡:

#ifndef _X_LOG_H_
#define _X_LOG_H_
#include 
<stdio.h>
#include 
<errno.h>

#ifdef USE_LOG4CPLUS
    #include 
<log4cplus/configurator.h>
    #include 
<string>
    
static log4cplus::Logger logger= log4cplus::Logger::getInstance("Log");
    
static void init_log(const std::string & path)
    
{
        log4cplus::PropertyConfigurator::doConfigure(path);   
    }

    #define XLOG_ALL        log4cplus::TRACE_LOG_LEVEL
    #define XLOG_TRACE        log4cplus::TRACE_LOG_LEVEL
    #define XLOG_DEBUG        log4cplus::DEBUG_LOG_LEVEL
    #define XLOG_INFO            log4cplus::INFO_LOG_LEVEL
    #define XLOG_NOTICE        log4cplus::INFO_LOG_LEVEL
    #define XLOG_WARNING    log4cplus::WARN_LOG_LEVEL
    #define XLOG_ERROR        log4cplus::ERROR_LOG_LEVEL
    #define XLOG_CRITICAL    log4cplus::FATAL_LOG_LEVEL

    #define X_LOG(l, ) \
    
do { \
        
if(logger.isEnabledFor(l)) { \
            
char __buf__internal__[2046]={0}; \
            snprintf(__buf__internal__,
2045,__VA_ARGS__); \
            logger.forcedLog(l, __buf__internal__, __FILE__, 

__LINE__); \
        }
 \
    }
 while(0);
#elif define USE_ACE_LOG
    #include 
"ace/Log_Msg.h"
    #include 
"ace/Trace.h"
    #define XLOG_ALL        LM_TRACE
    #define XLOG_TRACE        LM_TRACE
    #define XLOG_DEBUG        LM_DEBUG
    #define XLOG_INFO             LM_INFO
    #define XLOG_NOTICE        LM_NOTICE
    #define XLOG_WARNING    LM_WARNING
    #define XLOG_ERROR        LM_ERROR
    #define XLOG_CRITICAL        LM_CRITICAL
    #define X_LOG(l,
do{ \
        ACE_DEBUG((l,
"[%T|%t] %s-%s:%

d
",__FILE__,__FUNCTION__,__LINE__)); \
        ACE_DEBUG((l,__VA_ARGS__)); \
        }
while(0)
#
else
    #include 
<pthread.h>
    #include 
<time.h>
    #include 
<sys/time.h>
    #define XLOG_LEVEL 
0xFF
    typedef 
enum{
        XLOG_CRITICAL
=0x1,
        XLOG_ERROR
=0x2,
        XLOG_WARNING
=0x4,
        XLOG_NOTICE
=0x8,
        XLOG_INFO
=0x10,
        XLOG_DEBUG
=0x20,
        XLOG_TRACE
=0x40,
        XLOG_ALL
=0x80
    }
XLogLevel;
    #define X_LOG(l,
do{ \
        
if(XLOG_LEVEL&l){ \
                struct timeval now;\
                gettimeofday(
&now,0); \
                struct tm 
*ptm=localtime(&(now.tv_sec)); \
                printf(
"[%d|%d:%d:%d.%d] [%s/%s/%d] 

",pthread_self(),ptm->tm_hour,ptm->tm_min,ptm-

>tm_sec,now.tv_usec,__FILE__,__FUNCTION__,__LINE__); \
                printf( __VA_ARGS__); \
            }
 \
        }
while(0)
#endif

#define die(str) 
{X_LOG(XLOG_WARNING,str); return;}

#define die_0(str) 
{X_LOG(XLOG_WARNING,str); return 0; }

#define die_1(str) 
{X_LOG(XLOG_WARNING,str); return -1; }

#define die_ns(str) 
{X_LOG(XLOG_WARNING,str); return ""; }

/*safe func return empty,0,-1*/
#define SAFE_FUNC(func) 
if((func)<0) \
    
{ \
        X_LOG(XLOG_ERROR,
"[%s:%d]error!error[%d:%s]

\n
",__FILE__,__LINE__,errno,strerror(errno)); \
        exit(-1); \
    }


/*safe func but 1 err return empty,0,-1*/
#define SAFE_FUNC_BUT_ERR1(func,ERR1) 
do \
    
{ \
        
if((func)<0){ \
            X_LOG(XLOG_ERROR,
"[%s:%d]error!error[%d:%s]

\n
",__FILE__,__LINE__,errno,strerror(errno)); \
            if(errno!=ERR1) exit(-1); \
        }
 \
        
else break; \
    }
while(1)

/*safe func but 2 err return empty,0,-1*/
#define SAFE_FUNC_BUT_ERR2(func,ERR1,ERR2) 
do \
    
{ \
        
if((func)<0){ \
            X_LOG(XLOG_ERROR,
"[%s:%d]error!error[%d:%s]

\n
",__FILE__,__LINE__,errno,strerror(errno)); \
            if(errno!=ERR1&&errno!=ERR2)  exit(-1); \
        }
 \
        
else break; \
    }
while(1)
#endif

當(dāng)前的XLog.h文件實(shí)現(xiàn)了使用log4cplus、ace、printf三種方式,當(dāng)然可以隨意擴(kuò)展。die則是XLOG_WARNING的打印方式,SAFE_FUNC是XLOG_ERROR的打印方式。
如果要使用log4cplus,請(qǐng)定義USE_LOG4CPLUS宏,使用的時(shí)候在進(jìn)程開(kāi)始處,

#ifdef  USE_LOG4CPLUS
  init_log(
"log.properties");
#endif

以X_LOG的方式使用log4cplus,你可以對(duì)log4cplus一無(wú)所知。執(zhí)行你編譯好的程序前,在可執(zhí)行程序的目錄下建立log.properties文件,內(nèi)容你可以這樣寫:

# Define the root logger
log4cplus.rootLogger
=TRACE, consoleAppender, fileAppender

# Define a file appender named 
"consoleAppender"
log4cplus.appender.consoleAppender
=log4cplus::ConsoleAppender
log4cplus.appender.consoleAppender.layout
=log4cplus::PatternLayout
log4cplus.appender.consoleAppender.layout.ConversionPattern
=%-5p-[%t][%D{%H:%M:%%Q}]%m

# Define a file appender named 
"fileAppender"
log4cplus.appender.fileAppender
=log4cplus::RollingFileAppender
log4cplus.appender.fileAppender.MaxFileSize
=200KB
log4cplus.appender.fileAppender.File
=./log.log
log4cplus.appender.fileAppender.MaxBackupIndex
=3
log4cplus.appender.fileAppender.layout
=log4cplus::PatternLayout
log4cplus.appender.fileAppender.layout.ConversionPattern
=%-5p-[%t][%D{%H:%M:%%Q}]%m

有關(guān)log.properties文件的配置,可以自行去查找有關(guān)log4cplus的文章。如果你沒(méi)使用過(guò)log4cplus,ok,那么下載一個(gè)log4cplus,編譯,依據(jù)本文的XLog.h文件構(gòu)建一個(gè)系統(tǒng),嘗試以下,你一定會(huì)驚嘆log4cplus的強(qiáng)大與美妙。

posted on 2008-06-05 09:54 cppexplore 閱讀(7183) 評(píng)論(23)  編輯 收藏 引用

評(píng)論

# re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 必備外圍功能-log 2008-06-05 11:38 true
知識(shí)面很廣啊,不知工作中開(kāi)發(fā)什么呢  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 必備外圍功能-log[未登錄](méi) 2008-06-05 12:08 cppexplore
@true
呵呵 linux上的應(yīng)用服務(wù)器 軟交換服務(wù)器 流媒體服務(wù)器等。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 必備外圍功能-log 2008-06-05 12:28 true
汗。。。,我和你可能有些緣分,我也在linux開(kāi)發(fā)應(yīng)用服務(wù)器,語(yǔ)音板卡,信令。哈哈。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 必備外圍功能-log[未登錄](méi) 2008-06-05 12:48 cppexplore
還沒(méi)接觸過(guò)語(yǔ)音板卡 我們的應(yīng)用沒(méi)有媒體編解碼或者dtmf檢測(cè)的。有時(shí)間向你討教討教,留個(gè)聯(lián)系方式吧,我的gtalk/gmail是gamil.com的,msn是live.com的,名稱都是zongjinliang。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 必備外圍功能-log 2008-06-05 17:50 Kevin Lynx
日志對(duì)于一個(gè)系統(tǒng)來(lái)說(shuō)確實(shí)是必不可少的基礎(chǔ)模塊。
我用模板寫了個(gè)不依賴于具體‘寫’的日志類,簡(jiǎn)單的日志等級(jí)過(guò)濾。
///
/// @file kl_logger.h
/// @author Kevin Lynx
/// @date 4.21.2008
///
#ifndef ___KL_LOGGER_H_
#define ___KL_LOGGER_H_

#include <assert.h>
#include <stdarg.h>
#include <time.h>
#include <fstream>
#include "kl_compiler_cfg.h"

KL_COMMON_NAMESPACE_BEGIN

/// log level
enum log_level
{
LL_MIN = -1,
LL_ERROR,
LL_WARNING,
LL_INFO,
LL_DEBUG,
LL_MAX
};

///
/// default log pre-string, add system time and log level.
///
struct default_log_prestr
{
/// output pre-string in the buffer
/// @return the offset of the buf.
std::size_t operator() ( char *buf, int level )
{
char time[9];
char date[9];
_strtime( time );
_strdate( date );

const char *ll_desc = 0;
switch( level )
{
case LL_ERROR:
ll_desc = "ERROR";
break;
case LL_WARNING:
ll_desc = "WARNING";
break;
case LL_INFO:
ll_desc = "INFO";
break;
case LL_DEBUG:
ll_desc = "DEBUG";
break;

default:
ll_desc = "UNKNOWN";
}

// combine
sprintf( buf, "%s %s %s : ", date, time, ll_desc );
return strlen( buf ) ;
}
};

///
///
/// A simple logger class to write log information.
///
/// @param _Output where the log information to put, it must implement 'log( const char*)' function.
/// @param _PreStr used to write the pre-string of the log text like : 4.21.2008 : something.
/// @param string_size used when format string.(static buffer is more fast than dynamic buffer)
template <typename _Output, typename _PreStr = default_log_prestr, std::size_t _string_size = 1024>
class logger
{
public:
/// output object type
typedef _Output output_type;

/// pre-string type
typedef _PreStr prestr_type;

/// string size used when formatting strings.
enum
{
string_size = _string_size
};

public:
/// constructor
logger() :
_output( 0 ), _level( LL_DEBUG )
{
}

/// destructor
~logger()
{
}

/// set the output manager, you must call this function before you
/// log anything.
void set_output( output_type *ot )
{
assert( ot != 0 && "logger::set_output : invalid arguments." );
_output = ot;
}

/// write log text
void write_only( int level, const char *format, ... )
{
assert( _output != 0 && "logger::write_only : You must set up the output manager before you log anything." );
static char buf[string_size];

// checck the level
if( level > _level ) return ;

// format the string
va_list list;
va_start( list, format );
vsprintf( buf, format, list );
va_end( list );

// output the log text
_output->log( buf );
}

/// write log text and append prestring
void write( int level, const char *format, ... )
{
assert( _output != 0 && "logger::write : You must set up the output manager before you log anything." );
static char buf[string_size];

// checck the level
if( level > _level ) return ;

// append pre-string
std::size_t pos = _prestr( buf, level );

// format the string
va_list list;
va_start( list, format );
vsprintf( &buf[pos], format, list );
va_end( list );

// output the log text
_output->log( buf );
}

/// set log level
void set_level( int level )
{
assert( level > LL_MIN && level < LL_MAX && "logger::set_level : invalid arguments." );
_level = level;
}

/// get the log level
int get_level()
{
return _level;
}

private:
/// output manager to collect log text.
output_type *_output;
/// pre-str to append some text before the log text
prestr_type _prestr;
/// log level
int _level;
};

///
/// The file log output manager, write log text to the file.
///
class file_output
{
public:
/// constructor
file_output()
{
}

/// this constructor will open the file
file_output( const std::string filename, std::ios_base::openmode _Mode = std::ios_base::out ) :
_file_handle( filename.c_str(), _Mode )
{
}

/// destructor
~file_output()
{
}

/// open the file if it's not open
bool open( const std::string filename, std::ios_base::openmode _Mode = std::ios_base::out )
{
if( _file_handle.is_open() )
{
return false;
}

_file_handle.open( filename.c_str(), _Mode );
return _file_handle.is_open();
}

/// log
void log( const char *str )
{
assert( _file_handle.is_open() && "file_output::log : you cannot write anything before you open the file!" );
_file_handle << str ;
_file_handle.flush();
}

private:
/// output file
std::ofstream _file_handle;
};

KL_COMMON_NAMESPACE_END

#endif // end ___KL_LOGGER_H_  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 必備外圍功能-log 2008-06-05 19:44 cppexplore
呵呵 以為我的log框架你會(huì)喜歡,看來(lái)我錯(cuò)了。不過(guò)還有一句話“如果你沒(méi)使用過(guò)log4cplus,ok,那么下載一個(gè)log4cplus,編譯,......,嘗試以下,你一定會(huì)驚嘆log4cplus的強(qiáng)大與美妙。”  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-02 13:18 mono
logger如果建立多個(gè),日志文件會(huì)狂長(zhǎng),因?yàn)槊看握{(diào)用LOG4CPLUS_LEVEL,每個(gè)logger都記錄一次

我奇怪,logger.shutdown 好像沒(méi)有作用

看起來(lái)static 好像可以,但是如果你在多個(gè)地方都指定properties,logger還是會(huì)運(yùn)行多次,而
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS("log4cplus.properties"));
又不能static

當(dāng)然導(dǎo)入一次properties會(huì)記錄正確,我又不明白,如果你在某一個(gè)函數(shù)里聲明,它什么時(shí)候會(huì)消亡呢。我覺(jué)得在某一個(gè)函數(shù)里聲明properties,它就是全局的嗎,那我希望某個(gè)地方換一個(gè)properties,比如某個(gè)函數(shù)是在不同的路徑甚至機(jī)器下運(yùn)行,還能不能保證還是這個(gè)properties,或者根據(jù)當(dāng)前位置的相對(duì)路徑無(wú)法找到需要的properties



另外,lz的宏編譯錯(cuò)誤,我自己寫了一個(gè)宏

static log4cplus:tostringstream _str_buf;
static log4cplus::Logger logger= log4cplus::Logger::getInstance("filelogger");

X_LOG( logInfo, logLevel) \
_str_buf.clear();
_str_buf << logInfo;
logger.forceLog( logLevel, _str_buf.str(), __FILE__, __LINE__ )

在vs 2005下編譯成功,并且也確實(shí)記錄了,問(wèn)題就是,即使你指定properties,它也不按照格式配置記錄,而是自己把日志內(nèi)容按行紀(jì)錄,根本無(wú)視 時(shí)間、線程等等格式

這個(gè)宏與log4cplus本身的宏并沒(méi)有什么區(qū)別,為什么看起來(lái)并沒(méi)有讀properties呢

  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2008-12-02 19:05 cppexplore
@mono
#define USE_LOG4CPLUS
之后就編譯正確了吧,或者你把define USE_ACE_LOG那段去掉,可以用printf調(diào)式。
你的需求是什么樣子的?我用于server端程序,在main函數(shù)開(kāi)始,來(lái)句:
#ifdef USE_LOG4CPLUS
init_log("./log.properties");
#endif
之后就再就是正常的程序啟動(dòng)了,起各個(gè)協(xié)議棧、線程。當(dāng)然log也都是打印在一個(gè)log文件里。
server端程序是一直運(yùn)行的,不會(huì)退出,也就不存在消亡的問(wèn)題。
  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-10 11:34 guosha
very good,
博主用過(guò)log4c嗎?感覺(jué)如何?  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2008-12-10 11:56 cppexplore
@guosha
沒(méi)有用過(guò)。
log是個(gè)小功能,封裝下能做到透明使用基本就可以了。log4c依賴apr庫(kù),如果你的主體程序不是在apr上構(gòu)建的話,引入log4c不太舒服,呵呵。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2008-12-10 12:01 cppexplore
@mono,給你個(gè)可以編譯通過(guò)的宏,不知道你是win下還linux下,下面的宏都可以,另外流式的log不容易和printf、ace等對(duì)應(yīng),也看個(gè)人喜好,我是認(rèn)為printf的方式更容易格式化輸出。
#define USE_LOG4CPLUS
#ifdef USE_LOG4CPLUS
#include <log4cplus/configurator.h>
#include <string>
static log4cplus::Logger logger= log4cplus::Logger::getInstance("Log");
static void init_log(const std::string & path)
{
log4cplus::PropertyConfigurator::doConfigure(path);
}
#define XLOG_ALL log4cplus::TRACE_LOG_LEVEL
#define XLOG_TRACE log4cplus::TRACE_LOG_LEVEL
#define XLOG_DEBUG log4cplus::DEBUG_LOG_LEVEL
#define XLOG_INFO log4cplus::INFO_LOG_LEVEL
#define XLOG_NOTICE log4cplus::INFO_LOG_LEVEL
#define XLOG_WARNING log4cplus::WARN_LOG_LEVEL
#define XLOG_ERROR log4cplus::ERROR_LOG_LEVEL
#define XLOG_CRITICAL log4cplus::FATAL_LOG_LEVEL

#ifdef WIN32
#if (_MSC_VER < 1500)
#define vsnprintf _vsnprintf
#endif
void inline win_log( int l, const char *format, ... )
{
if(logger.isEnabledFor(l)) {
schar buf[2046]={0};
va_list list;
va_start( list, format );
vsnprintf( buf, (size_t)2045,format, list );
va_end( list );
logger.forcedLog(l, buf, __FILE__, __LINE__);
}
}
#define X_LOG win_log
#else
#define X_LOG(l, ...) \
do { \
if(logger.isEnabledFor(l)) { \
char __buf__internal__[2046]={0}; \
snprintf(__buf__internal__,2045,__VA_ARGS__); \
logger.forcedLog(l, __buf__internal__, __FILE__, __LINE__); \
} \
} while(0)
#endif  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-17 21:55 田伯光
樓主,多進(jìn)程可以用嗎?  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-17 22:16 田伯光
樓主, 是把log4cplus編譯成一個(gè)靜態(tài)庫(kù)或是動(dòng)態(tài)庫(kù)后就直接使用你這個(gè)套上去就可以用嗎?  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-17 22:35 田伯光
看上去我好像已經(jīng)弄明白怎么用了, 不知道博主可有比較完備一點(diǎn)的有關(guān)LOG配置的文檔? 另外多進(jìn)程程序使用這個(gè)log系統(tǒng)會(huì)不會(huì)有什么問(wèn)題?  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2008-12-18 18:54 cppexplore
@田伯光
多個(gè)進(jìn)程指向同一個(gè)文件的話,的確都可以寫進(jìn)去。至于是不是穩(wěn)定就不清楚了,呵呵,我一直是單進(jìn)程多線程下使用,偶爾忘記程序已經(jīng)啟動(dòng),第二次啟動(dòng),同樣會(huì)把log寫進(jìn)文件。
你多測(cè)試下吧。
log4cplus的配置文件的配置方式網(wǎng)上不少,或者你留個(gè)郵箱,我發(fā)給你。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-23 15:30 田伯光
@cppexplore
guosha167@yahoo.com.cn

謝謝  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-23 16:54 田伯光
多進(jìn)程的話,不知道它是不是可以做到在一個(gè)進(jìn)程內(nèi)改了配置,自動(dòng)的其它進(jìn)程也可以使用更改過(guò)后的配置,并且不需要重新啟動(dòng)程序。最好能做到交互式的,在程序運(yùn)行期間能動(dòng)態(tài)控制Loger的打印行為。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2008-12-23 21:18 cppexplore
@田伯光
呵呵,多進(jìn)程一定不能共享對(duì)象,除非這個(gè)對(duì)象在共享內(nèi)存中,共享內(nèi)存中的對(duì)象又要注意互斥問(wèn)題。最好的辦法還是各進(jìn)程用自己的進(jìn)程的log對(duì)象。運(yùn)行期間動(dòng)態(tài)改變log的級(jí)別,可以去代碼中找答案,或者你等我有了這個(gè)需求,我改好告訴你,呵呵。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2008-12-23 23:24 田伯光
@cppexplore
是這樣的, 我以前寫的簡(jiǎn)單的Log模塊就是用共享內(nèi)存把log的管理結(jié)構(gòu)共享出來(lái), 這樣動(dòng)態(tài)控制只需要更改這個(gè)結(jié)構(gòu)的內(nèi)容就可以了,但我以前寫的只是控制一下級(jí)別跟打印的目的地,沒(méi)有這個(gè)功能那么多,呵呵. C++我不熟悉, 所以不想去研究這個(gè)的代碼,故問(wèn)你一下以得到現(xiàn)成結(jié)果.
  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2008-12-24 09:20 cppexplore
@田伯光
log4cplus是線程安全的。多進(jìn)程共享內(nèi)存的方式使用對(duì)象,和多線程的方式是一樣的。你可以壓力下測(cè)試下,呵呵。
另外,打印到syslogd和打印到socket也是多進(jìn)程打印log的備選方案。
log系統(tǒng)用開(kāi)源也不是因?yàn)樗鼈児δ軓?qiáng)大,主要的好處是它們充分考慮了IO輸出的效率(開(kāi)辟內(nèi)存池,延遲批量輸出),第二個(gè)是系統(tǒng)宕掉時(shí)候,log打印的準(zhǔn)確性。另外用宏隔離,也方便以后發(fā)現(xiàn)更好log系統(tǒng)時(shí)候替換。  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log 2009-02-08 18:07 sashion
能否介紹一下log4cplus如何支持文件轉(zhuǎn)儲(chǔ)?能在core dump 之前把所有的對(duì)象都dump到日志中嗎?是如何實(shí)現(xiàn)的?  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2009-02-19 10:36 cppexplore
@sashion
不曉的啊,可以去看源代碼 :)  回復(fù)  更多評(píng)論
  

# re: 【原創(chuàng)】技術(shù)系列之 必備外圍功能-log[未登錄](méi) 2011-06-04 13:31 cppexplore
2年前對(duì)日志完善了不少,以前的錯(cuò)誤引導(dǎo)更正下
@田伯光
多進(jìn)程打印問(wèn)題:
不可以多進(jìn)程打印, 除了寫不能保證原子性,還有文件更換時(shí)的問(wèn)題.
共享內(nèi)存共享log對(duì)象可以, 這樣還不如各自打印獨(dú)立文件, 同時(shí)使用遠(yuǎn)程syslog方式統(tǒng)一打印到遠(yuǎn)程(需要自己實(shí)現(xiàn)appender)

動(dòng)態(tài)生效問(wèn)題:
可使用ConfigureAndWatchThread類達(dá)到目的, 同時(shí)log4cplus中有不少bug,使用這個(gè)功能時(shí) 要修改不少地方.

@sashion
上上個(gè)我的留言里說(shuō)錯(cuò)了很多地方.
log4cplus沒(méi)有提供延遲輸出的策略, 新的維護(hù)者有計(jì)劃增加異步,還沒(méi)增加.實(shí)現(xiàn)異步延遲打印,需要自己進(jìn)一步封裝實(shí)現(xiàn).

"能在core dump 之前把所有的對(duì)象都dump到日志中嗎?"
不能. 因log4cplus沒(méi)有提供延遲輸出的策略, 日志同步打印,也不存在這個(gè)問(wèn)題. 若自己實(shí)現(xiàn)異步延遲輸出的話, 延遲輸出的部分可以使用共享內(nèi)存,另可捕獲信號(hào)做一定補(bǔ)償.  回復(fù)  更多評(píng)論
  


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久亚洲欧美| 亚洲一区二区三区激情| 久久精品99国产精品| 狠狠做深爱婷婷久久综合一区| 性刺激综合网| 久久久综合香蕉尹人综合网| 在线观看精品| 亚洲蜜桃精久久久久久久| 国产精品豆花视频| 久久午夜精品| 欧美激情精品久久久六区热门| 夜夜爽av福利精品导航 | 99成人免费视频| 在线视频日韩精品| 国产一区二区三区直播精品电影 | 欧美在线视频免费观看| 在线欧美亚洲| 在线视频中文亚洲| 精品动漫3d一区二区三区| 亚洲精品中文字幕有码专区| 国产精品色午夜在线观看| 欧美 日韩 国产一区二区在线视频 | 久久精品国产亚洲一区二区| 久久综合电影| 亚洲欧美日韩在线一区| 另类亚洲自拍| 午夜精品久久| 欧美成人亚洲| 久久午夜电影网| 欧美视频在线观看 亚洲欧| 噜噜噜噜噜久久久久久91| 国产精品国产三级国产aⅴ浪潮 | 亚洲一级片在线观看| 亚洲国产高潮在线观看| 亚洲欧美日韩国产综合精品二区| 亚洲国产精品一区| 欧美一区二区三区日韩| 在线一区观看| 欧美劲爆第一页| 久久综合国产精品| 国产欧美日韩精品在线| aa亚洲婷婷| 99国产精品99久久久久久| 久久久久久噜噜噜久久久精品| 亚洲欧美一区二区三区极速播放 | 午夜欧美精品久久久久久久| 欧美精品一二三| 99精品热视频只有精品10| 欧美一级视频一区二区| 99日韩精品| 欧美二区不卡| 免费日韩精品中文字幕视频在线| 国产精品国产三级国产专区53| 亚洲国产精品成人| 久久久久久亚洲综合影院红桃| 欧美一区激情| 先锋影院在线亚洲| 欧美日韩国产精品专区| 亚洲第一综合天堂另类专| 国产综合网站| 欧美一级久久久| 亚洲欧美中文日韩在线| 欧美日韩免费在线视频| 亚洲激情在线| 一区二区三区www| 欧美精品免费播放| 亚洲精品四区| 一区二区三区国产在线| 欧美日韩午夜精品| 亚洲视频 欧洲视频| 午夜精品视频一区| 国产乱子伦一区二区三区国色天香 | 久久在线免费观看| 久久久国产成人精品| 国产亚洲制服色| 久久久www成人免费精品| 久久视频一区二区| 在线免费观看欧美| 蜜桃av噜噜一区| 日韩视频一区二区三区在线播放免费观看| 亚洲伦理久久| 国产精品av一区二区| 亚洲欧美日韩一区在线观看| 久久久久久久久岛国免费| 亚洲国产99| 欧美日韩一区二区欧美激情| 亚洲欧美日韩成人高清在线一区| 久久久久久久久久久久久9999| 伊人久久综合97精品| 欧美精品一区二区三区蜜桃| 亚洲永久免费av| 美国三级日本三级久久99| 日韩视频免费观看高清在线视频| 欧美香蕉视频| 久久精品免费播放| 亚洲毛片在线观看| 久久精品国产v日韩v亚洲| 亚洲国产一区二区三区a毛片| 欧美日韩一区免费| 久久狠狠一本精品综合网| 亚洲激情国产| 久久九九电影| 在线亚洲国产精品网站| 亚洲少妇在线| 久久综合网络一区二区| 日韩视频在线免费观看| 久久精品视频一| 日韩西西人体444www| 国产日韩亚洲欧美综合| 欧美v亚洲v综合ⅴ国产v| 亚洲女人天堂av| 99视频热这里只有精品免费| 欧美视频免费在线观看| 久久精品噜噜噜成人av农村| 日韩视频免费观看| 噜噜噜91成人网| 亚洲欧美日韩人成在线播放| 亚洲欧洲久久| 国产自产v一区二区三区c| 欧美三区不卡| 欧美国产一区二区在线观看 | 亚洲福利视频网站| 国产麻豆综合| 国产精品99免视看9| 欧美高清自拍一区| 久久国产毛片| 欧美一区二区三区在线观看| 一区二区91| 99人久久精品视频最新地址| 亚洲高清视频的网址| 欧美不卡视频一区发布| 老司机午夜精品视频在线观看| 亚洲欧美在线高清| 一区二区三区欧美| 99精品热6080yy久久| 亚洲精品久久久久久久久久久 | 国产精品xnxxcom| 欧美日韩亚洲视频| 欧美日本高清| 欧美日韩免费在线观看| 欧美日本在线| 欧美日韩一区不卡| 欧美日韩在线视频首页| 欧美视频1区| 国产精品白丝av嫩草影院| 国产精品电影网站| 国产女主播一区二区三区| 国产精品一区二区三区乱码| 国产麻豆9l精品三级站| 国产视频一区免费看| 国内久久视频| 亚洲福利视频二区| 亚洲另类春色国产| 一本久久综合| 亚洲女人av| 久久噜噜噜精品国产亚洲综合| 六月婷婷久久| 亚洲乱码视频| 亚洲欧美日韩国产综合| 久久久久国产精品一区| 欧美二区乱c少妇| 欧美日韩喷水| 国产一区二区三区免费观看| 在线免费观看日韩欧美| 一区二区三区精品久久久| 亚洲欧美精品一区| 亚洲午夜精品17c| 亚洲已满18点击进入久久| 亚洲免费小视频| 久久精品2019中文字幕| 男女精品视频| 9国产精品视频| 久久国产视频网站| 欧美成人r级一区二区三区| 欧美性大战xxxxx久久久| 国产综合欧美| 韩国三级电影一区二区| 欧美日韩在线亚洲一区蜜芽| 国产网站欧美日韩免费精品在线观看| 在线观看日韩欧美| 亚洲午夜精品国产| 免费不卡亚洲欧美| 一区二区三区四区蜜桃| 久久久不卡网国产精品一区| 欧美色中文字幕| 亚洲成人原创| 欧美在线视频免费播放| 亚洲国产综合在线看不卡| 性一交一乱一区二区洋洋av| 欧美精品三级日韩久久| 国精品一区二区| 亚洲免费伊人电影在线观看av| 亚洲视频欧美视频| 久久亚洲欧美| 亚洲在线观看免费| 欧美精品一区二区高清在线观看| 国产日韩精品一区二区浪潮av| 日韩视频在线你懂得| 欧美成年人网站| 欧美伊人久久大香线蕉综合69|