开源日志库log4c存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;

本文主要是介绍开源日志库log4c存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

开源日志库log4c存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;这样在ARM中应用时,当应用重启了,但是log0还没有达到maxsize,就切换了一个新的文件,会造成空间浪费,网上查了好久,log4c没有提供这样的接口,维护别人的代码,用到了log4c这个库,只能修改log4c的源码了。

源码修改的地方如下:

static int get_file_size(const char *filename)
{
FILE*fp;
if((fp=fopen(filename,"rb"))==NULL)
{
return -1;
}
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
fclose(fp);
return len;
}
/*******************************************************************************/
static int sizewin_rollover(log4c_rollingpolicy_t *this, FILE ** current_fpp ){
int rc = 0;
rollingpolicy_sizewin_udata_t *swup = log4c_rollingpolicy_get_udata(this);
int k = 0;
int i = 0;
sd_debug("sizewin_rollover[");
/* Starting at the last_index work back renaming the files and
leaving space for the .0 file.
If the last index is negative then it means the file doesn't exist
so we create the first file
*/
if ( !swup || !swup->sw_logdir){
sd_error("rollingpolicy '%s' not yet configured (logdir,prefix etc.)",
log4c_rollingpolicy_get_name(this));
} else {
swup->sw_last_index = sizewin_get_last_index(swup);  
k = swup->sw_last_index;
if ( k < 0 ) {
sd_debug("creating first file");
if (sizewin_open_zero_file(swup->sw_filenames[0], current_fpp,1)){
swup->sw_flags |= SW_LAST_FOPEN_FAILED;
sd_error("open zero file failed");
} else{
swup->sw_flags &= !SW_LAST_FOPEN_FAILED;
}
swup->sw_last_index = 0;
} else {
sd_debug("rolling up existing files");
if ( k == swup->sw_conf.swc_file_max_num_files-1) {    
if(unlink(swup->sw_filenames[k])){
sd_error("unlink failed");
rc = 1;
} else {
k = swup->sw_conf.swc_file_max_num_files-2;
}
} else {
/* not yet reached the max num of files
* so there's still room to rotate the list up */    
}
/* If there's a current open fp, close it.*/
if ( !(swup->sw_flags & SW_LAST_FOPEN_FAILED) && *current_fpp) {
if(fclose(*current_fpp)){
sd_error("failed to close current log file");
rc = 1;
}
} else {
if( (swup->sw_flags & SW_LAST_FOPEN_FAILED)){
sd_debug("Not closing log file...last open failed");
} else if (*current_fpp == 0) {
sd_debug("No log file currentlty open...so not closing it");
}else {
sd_debug("Not closing current log file...not sure why");
}
}
/* Now, rotate the list up if all seems ok, otherwise 
* don't mess with teh files if something seems to have gone wrong
*/
int new_file_flag=0;
if ( !rc){
sd_debug("rotate up , last index is %d", k);
int len= get_file_size(swup->sw_filenames[0]);
int max_len=swup->sw_conf.swc_file_maxsize/100000*100000;
if(len>max_len ||len==-1)
{
i = k;
while ( i >= 0 ) {
sd_debug("Renaming %s to %s",
swup->sw_filenames[i], swup->sw_filenames[i+1]);
if(rename( swup->sw_filenames[i], swup->sw_filenames[i+1])){
sd_error("rename failed"); 
rc = 1;
// break;
}
i--;
}
if ( !rc){
swup->sw_last_index = k + 1;
}
new_file_flag=1;
}
} else {
sd_debug("not rotating up--some file access error");
}
/* Now open up the 0'th file for writing */
if (sizewin_open_zero_file(swup->sw_filenames[0], current_fpp,new_file_flag)){
swup->sw_flags |= SW_LAST_FOPEN_FAILED;
sd_error("open zero file failed");
rc = 1;
} else{
swup->sw_flags &= !SW_LAST_FOPEN_FAILED;
rc = 0;
}
}
sd_debug("current file descriptor '%d'", fileno(*current_fpp));
}
sd_debug("]");
return(rc);
}


 

static int sizewin_open_zero_file(char *filename, FILE **fpp,int flag ){
int rc = 0;
sd_debug("sizewin_open_zero_file['%s'", filename);
if(flag)
{
*fpp = fopen(filename, "w+");
}else
{
*fpp = fopen(filename, "a+");
}
if ( (*fpp) == NULL){
sd_error("failed to open zero file '%s'--defaulting to stderr--error='%s'",
filename, strerror(errno));   
*fpp = stderr;
rc = 1;
}  
/* unbuffered mode at the filesystem level
xxx make this configurable from the outside ?
*/
setbuf(*fpp, NULL);    
sd_debug("]");  
return(rc);
}


 

 

以下内容转自互联网,版权归原作者所有:

http://xueqi.iteye.com/blog/1570013

1.Log工具简单比较

Log4cpp & Log4CPlus:C++的日志库,可移植移性相对差些
Log4c:C的日志库,基本上都是一些纯c的东西,移植性较好

2.Log4c的基本概念
Log4c中有三个重要的概念, Category, Appender, Layout。
  Category用于区分不同的日志,在一个程序中我们可以通过Category来指定很多的日志。
  Appdender用于描述输出流,通过为Category来指定一个Appdender,可以决定将log信息来输出到什么地方去,比如stdout, stderr, rollingfile等等。
  Layout用于指定日志信息的格式,通过为Appender来指定一个Layout,可以决定log信息以何种格式来输出,比如是否有带有时间戳, 是否包含文件位置信息等,以及他们在一条log信息中的输出格式的等。
Category, Appender, Layout三者之间的关系,一个Category需要为其指定一个appender, 一个appender亦要为其指定一个layout。
另外,对于文件类型输出还有一个rollingpolicy。rollingpolicy用于描述文件输出的配置策略。

3.关于配置
配置文件示例如下:

<!DOCTYPE log4c SYSTEM "">
<log4c version="1.2.0">
  <config>
    <bufsize>0</bufsize>
    <debug level="0"/>
    <nocleanup>0</nocleanup>
  </config>
  
  <layout name="dated" type="dated_l"/>
  
  <!-- appenders ===================================== -->
    <appender name="LoadBusinessLog" type="rollingfile" logdir="../etc/log"
       prefix="LoadBusiness-" layout="dated_l" rollingpolicy="Policy1" />
 
    <appender name="CataRollingFileAppender" type="rollingfile" logdir="../etc/log/"
       prefix="testLog" layout="dated" rollingpolicy="RollingPolicy" />

    <!-- category ========================================= -->
    <category name="root" priority="notice"/>
    <category name="framework" priority="info" appender="FrameLog" />
    <category name="test.log" priority="trace" appender="CataRollingFileAppender" />

    <!-- policy ======================================= -->
    <rollingpolicy name="Policy1" type="timewin" timetype="1" maxnum="10" />
    <rollingpolicy name="RollingPolicy" type="sizewin" maxsize="102400" maxnum="10" />
</log4c>

3.1 category
name:日志的名称
priority:日志的优先级,共有fatal、alert、crit、error、warn、notice、info、debug、trace、notset和unknown11个级别,其级别逐步递增,记录在日志中的数据为小于等于指定级别的数据。
appender:输出流类型名称,为appender节点的name属性的值。

3.2 appender
name:输出流名称
type:输出流类型,共有stream、syslog、rollingfile三大类
layout:输出日志的格式的名称,为layout节点的name属性的值。
rollingpolicy:输出日志文件配置策略名称,为rollingpolicy节点的name属性的值。
rollingpolicy的timewin类型的日志输出为自定义类型

3.3 layout
name:输出日志的格式名称
type:输出日志格式的类型,共有base 、dated、dated_l等格式类型,对于自定义类型也有配置在这里,否则不能够加载。
base:%P %c - %m/n
     "%P" 日志信息的优先级
     "%c" 日志的名称
     "%m" 日志信息内容
dated:%d %P %c - %m/n
     "%d" 日志信息产生的时间,UTC格式yyyymmdd hh:mm:ss.mis
     "%P" 日志信息的优先级
     "%c" 日志的名称
     "%m" 日志信息内容
dated_l:%d %P %c - %m/n (源代码里面没有,自己增加的)
     "%d" 日志信息产生的时间,本地时间格式yyyymmdd hh:mm:ss
     "%P" 日志信息的优先级
     "%c" 日志的名称
     "%m"日志信息内容

3.4 rollingpolicy
name:日志文件输出的配置策略名称。
type:日志文件输出的配置策略的类型,有sizewin一种类型。
maxsize:输出日志文件的最大值。默认值为20KB
maxnum:保存的历史日志文件总数。默认值为5

3.5 配置文件的路径
${ LOG4C_RCPATH }/log4crc  //环境变量中设置的配置文件夹下log4crc
${HOME}/.log4crc       //HOME文件夹下log4crc
./log4crc          //当前可执行文件夹下log4crc

4、Log4c的基本使用

头文件 (直接引用log4c.h程序编译出错,因此只引用需要的头文件)
extern "C" {
#include <log4c/init.h>
#include <log4c/category.h>
}

cpp文件
//初始化
log4c_init();
//获取一个已有的category
log4c_category_t* mycat = log4c_category_get("cata.log ");
//用该category进行日志输出,优先级为DEBUG,输出信息为 "Hello World!"
log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Hello World!");
//析构
log4c_fini();

//在日志输出过程中可以进行格式化输出:
log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "Error code = %d", 12345);
//对于格式化输出也可以有如下写法:
void CLog::Trace(const char * format, ... )
{
   if (log4c_category_is_priority_enabled(mycat, LOG4C_PRIORITY_TRACE))
   {
    a_list argptr;
    va_start(argptr, format);

    log4c_category_vlog(mycat, LOG4C_PRIORITY_TRACE, format, argptr);

    va_end(argptr);
   }
}

5.自定义Logout

5.1 添加在Log4c源代码中的流程


在log4c-1.2.0/src/文件夹添加相应的头文件和实现文件,如examplelayout.h和examplelayout.c文件
编辑log4c-1.2.0/src/log4c/Makefile.in
在am__liblog4c_la_SOURCES_DIST中添加examplelayout.c
在am_liblog4c_la_OBJECTS中添加examplelayout. lo
在liblog4c_la_SOURCES 中添加examplelayout.c
在pkginclude_HEADERS中添加 examplelayout.h
添加@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ examplelayout.Plo@am__quote@
编辑log4c-1.2.0/src/log4c/Makefile.am
在liblog4c_la_SOURCES中添加examplelayout.c
在pkginclude_HEADERS中添加examplelayout.h
编辑log4c-1.2.0/src/init.c
添加#include <examplelayout.h>
在static const log4c_layout_type_t * const layout_types[]数组中添加新添加的layout_type函数指针
5.2在工程中添加自定义日志格式
实现自定义格式的主要函数:

static const char* cat_format(
  const log4c_layout_t* a_layout,
  const log4c_logging_event_t*a_event)
{
  static char buffer[4096];

  /*
   * For this formatter we put the category up front in the log message
   */
  sprintf(buffer, "[%s][LINE:%d][FILE:%s] %s", a_event->evt_category,
    a_event->evt_loc->loc_line, a_event->evt_loc->loc_file, a_event->evt_msg);

  return buffer;
}

const log4c_layout_type_t log4c_layout_type_cat = {
  "test_cat",  //格式名称,用于配置文件的设置
  cat_format,  //格式定义函数
    

5.3将自定义格式添加到Log4c的配置中

int init_example_formatters()
{
  log4c_layout_type_set(&log4c_layout_type_cat);//自定义格式类型函数指针
}

  

5.4自定义格式的使用
//执行自定义格式初始化

init_example_formatters();
//执行Log4c的初始化
log4c_init();
……
  
  

#ff00806.自定义Appender

6.1实现自定义输出流的主要函数:

static int test_file_append(log4c_appender_t* a_appender,
        const log4c_logging_event_t* a_event)
{
  FILE* fp = log4c_appender_get_udata(a_appender);
  /*
   return fprintf(fp, "[%s] [%s] [%d] [%d] [%s] [%s] [%d]/n%s",
   log4c_appender_get_name(this),
   a_event->evt_category,
   a_event->evt_priority,
   a_event->evt_timestamp.tv_sec*1000000 + a_event->evt_timestamp.tv_usec,
   a_event->evt_msg,
   a_event->evt_loc->loc_file,
   a_event->evt_loc->loc_line,
   a_event->evt_rendered_msg);
  */
  return fprintf(fp, "%s/n", a_event->evt_rendered_msg);
}

static int test_open(log4c_appender_t* a_appender)
{
  FILE* fp = log4c_appender_get_udata(a_appender);
  
  if (fp)
   return 0;
  if ( (fp = fopen(log4c_appender_get_name(a_appender), "a+")) == NULL)
   fp = stderr;
  /* unbuffered mode */
  setbuf(fp, NULL);
  log4c_appender_set_udata(a_appender, fp);
  return 0;
}

static int test_close(log4c_appender_t* a_appender)
{
  FILE* fp = log4c_appender_get_udata(a_appender);
    return (fp ? fclose(fp) : 0);
}
const log4c_appender_type_t log4c_appender_type_test_file = {
  "test_file",    //输出流的名称,用于配置文件设置
   test_open,     //打开输出流的函数
   test_file_append, //给输出流追加日志信息的函数
   test_close,    //关闭输出流的函数
};
  

6.2将自定义输出流添加到Log4c的配置中

int init_example_appenders()
{
  log4c_appender_type_set (&log4c_appender_type_test_file);//自定义输出流类型的函数指针
}
  

6.3自定义输出流的使用

//执行自定义格式初始化
init_example_appenders();
//执行Log4c的初始化
log4c_init();
……

  

7.自定义rollingpolicy
源代码中有一个sizewin的rollingpolicy,是根据文件大小进行生成日志控制的。
在这里添加一个根据时间的控制日志输出的策略,实现代码如下:

7.1 rollingpolicy_type_timewin.h

#ifndef log4c_policy_type_timewin_h
#define log4c_policy_type_timewin_h


#include <log4c/defs.h>
#include <log4c/rollingpolicy.h>

__LOG4C_BEGIN_DECLS

LOG4C_API const log4c_rollingpolicy_type_t log4c_rollingpolicy_type_timewin;

typedef struct __timewin_udata rollingpolicy_timewin_udata_t;

#define TIME_TYPE_HOUR 0
#define TIME_TYPE_DAY  1
#define TIME_TYPE_MONTH 2
#define TIME_TYPE_YEAR 3

#define ROLLINGPOLICY_TIME_DEFAULT_MAX_NUM_FILES   100
#define ROLLINGPOLICY_TIME_DEFAULT_FILE_TYPE     TIME_TYPE_DAY

LOG4C_API rollingpolicy_timewin_udata_t *timewin_make_udata(void);

LOG4C_API int timewin_udata_set_file_time_type(
               rollingpolicy_timewin_udata_t * swup,
         long time_type);
                                                        
LOG4C_API int timewin_udata_set_max_num_files(
               rollingpolicy_timewin_udata_t * swup,
             long max_num);
                             
LOG4C_API int timewin_udata_set_appender(
               rollingpolicy_timewin_udata_t * swup,
         log4c_appender_t* app);

__LOG4C_END_DECLS


#endif
  


7.2 rollingpolicy_type_timewin.c

  
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
#include <log4c/appender.h>
#include <log4c/rollingpolicy.h>
#include <log4c/rollingpolicy_type_timewin.h>

#include "appender_type_rollingfile.h"
#include <sd/malloc.h>
#include <sd/error.h>
#include <sd/sd_xplatform.h>
#include <sd/sprintf.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/* Internal structs that defines the conf and the state info
* for an instance of the appender_type_rollingfile type.
*/  
struct __timewin_conf { 
 long swc_file_time_type;
 long swc_file_max_num_files;
};

struct __timewin_udata {
 struct __timewin_conf sw_conf;
 rollingfile_udata_t *sw_rfudata;
 const char *sw_logdir;
 const char *sw_files_prefix;
 char *sw_curfileflag;
 char *sw_prefileflag;
 int sw_flags;
};

/***************************************************************************/

static int timewin_init(log4c_rollingpolicy_t *this, rollingfile_udata_t* rfup);
static int timewin_rollover(log4c_rollingpolicy_t *this, FILE **current_fpp );
static int timewin_is_triggering_event(
          log4c_rollingpolicy_t *this,
          const log4c_logging_event_t* a_event,
          long current_file_size);
static int timewin_fini(log4c_rollingpolicy_t *this);

static char* timewin_get_filename(rollingpolicy_timewin_udata_t * swup);
static int timewin_check_update_fileflag(rollingpolicy_timewin_udata_t * swup);
static int timewin_open_file(char *filename, FILE **fpp );
static int timewin_copy_string(char** szDest, const char* src);

/*******************************************************************************
       Policy interface: init, is_triggering_event, rollover
*******************************************************************************/

static int timewin_is_triggering_event(
          log4c_rollingpolicy_t *this,
          const log4c_logging_event_t* a_event,
          long current_file_size){
 int decision = 0;
 rollingpolicy_timewin_udata_t *swup = log4c_rollingpolicy_get_udata(this);

 sd_debug("timewin_is_triggering_event[");

 decision = timewin_check_update_fileflag(swup);
  
 if (decision)
 {
  sd_debug("triggering event"); 
 }
 else
 {
  sd_debug("not triggering event");
 }

 sd_debug("]"); 

 return(decision);
}

/*******************************************************************************/

static int timewin_rollover(log4c_rollingpolicy_t *this, FILE ** current_fpp ){
  int rc = 0;
  rollingpolicy_timewin_udata_t *swup = log4c_rollingpolicy_get_udata(this);
  int k = 0;
  char * szFileName = NULL;

  sd_debug("timewin_rollover[");

  if ( !swup || !swup->sw_logdir){
    sd_error("rollingpolicy '%s' not yet configured (logdir,prefix etc.)",
    log4c_rollingpolicy_get_name(this));
  }
  else
  {
    k = swup->sw_flags;
 
    if (k > 0 || *current_fpp == NULL)
    {
      szFileName = timewin_get_filename(swup);
      if (*current_fpp)
      {
        if(fclose(*current_fpp)){
          sd_error("failed to close current log file");
          rc = 1;
        }
      }
      if (!rc && timewin_open_file(szFileName, current_fpp)){
        sd_error("open zero file failed");
      }
      free(szFileName);
    }
  }
  sd_debug("]");
  return(rc);
}

/*******************************************************************************/

static int timewin_init(log4c_rollingpolicy_t *this, rollingfile_udata_t *rfup){
 rollingpolicy_timewin_udata_t *swup = NULL;

 sd_debug("timewin_init[");
 if (!this){
  goto timewin_init_exit;
 }
 
 swup = log4c_rollingpolicy_get_udata(this);
 if ( swup == NULL ){
  swup = timewin_make_udata();
  log4c_rollingpolicy_set_udata(this, swup);
 }
 
 swup->sw_logdir = rollingfile_udata_get_logdir(rfup);
 swup->sw_files_prefix = rollingfile_udata_get_files_prefix(rfup);
 timewin_check_update_fileflag(swup);

timewin_init_exit:
 sd_debug("]");

 return(0);
}

/*******************************************************************************/

static int timewin_fini(log4c_rollingpolicy_t *this){
 rollingpolicy_timewin_udata_t *swup = NULL;
 int rc = 0;

 sd_debug("timewin_fini[ ");
 if (!this){
  goto timewin_fini_exit;
 }
 
 swup = log4c_rollingpolicy_get_udata(this);
 if (!swup){
  goto timewin_fini_exit;
 }

 if (swup->sw_curfileflag)
 {
    free(swup->sw_curfileflag);
 }
  
 if (swup->sw_prefileflag)
 {
    free(swup->sw_prefileflag);
 }
 
 swup->sw_flags = 0;

 /* logdir and files_prefix are just pointers into the rollingfile udata
 * so they are not ours to free--that will be done by the free call to
 * the rollingfile appender
 */
 sd_debug("freeing timewin udata from rollingpolicy instance");
 free(swup);
 log4c_rollingpolicy_set_udata(this,NULL);
 
timewin_fini_exit:
 sd_debug("]");
 
 return(rc);
}

/*******************************************************************************
              timewin specific conf functions
*******************************************************************************/

LOG4C_API rollingpolicy_timewin_udata_t *timewin_make_udata(void)
{
 rollingpolicy_timewin_udata_t *swup = NULL;
 swup = (rollingpolicy_timewin_udata_t *)sd_calloc(1,
               sizeof(rollingpolicy_timewin_udata_t));
 timewin_udata_set_file_time_type(swup,
         ROLLINGPOLICY_TIME_DEFAULT_FILE_TYPE);
  
 timewin_udata_set_max_num_files(swup,
                 ROLLINGPOLICY_TIME_DEFAULT_MAX_NUM_FILES);

 swup->sw_curfileflag = 0;
 swup->sw_prefileflag = 0;
 swup->sw_flags = 0;
 return(swup);

}

/*******************************************************************************/

LOG4C_API int timewin_udata_set_file_time_type(rollingpolicy_timewin_udata_t * swup,
           long time_type){

 swup->sw_conf.swc_file_time_type = time_type;

 return(0);
 
}

/****************************************************************************/

LOG4C_API int timewin_udata_set_max_num_files(rollingpolicy_timewin_udata_t *swup,
           long max_num){

 swup->sw_conf.swc_file_max_num_files = max_num;

 return(0);
}

/****************************************************************************/

LOG4C_API int timewin_udata_set_rfudata(rollingpolicy_timewin_udata_t *swup,
           rollingfile_udata_t *rfup ){

 swup->sw_rfudata = rfup;

 return(0);
}

/*****************************************************************************
            private functions
*****************************************************************************/

/****************************************************************************/
static char* timewin_get_filename(rollingpolicy_timewin_udata_t* swup){
 long filename_len = 0;
 char *s = NULL;
 filename_len = strlen(swup->sw_logdir) + 1 +
         strlen(swup->sw_files_prefix) + 1 + 15; // a margin /
 s = (char *)malloc(filename_len);   
 sprintf( s, "%s%s%s%s%s", swup->sw_logdir,
    FILE_SEP, swup->sw_files_prefix, swup->sw_curfileflag, ".log");     
 return(s);
}

/********************************************************************************/
static int timewin_check_update_fileflag(rollingpolicy_timewin_udata_t * swup)
{
  struct tm  tm;
  time_t timep;
  time(&timep);
  char buf[11];
  memset(buf, 0, 11);

#ifndef _WIN32
#ifndef __HP_cc
#warning gmtime() routine should be defined in sd_xplatform
#endif
  localtime_r(&timep, &tm);
#else
  /* xxx Need a CreateMutex/ReleaseMutex or something here
   */
  {
  struct tm *tmp = NULL;
  tmp = localtime(&timep);
  tm = *tmp; /* struct copy */
  }
#endif
  swup->sw_flags = 0;
  switch (swup->sw_conf.swc_file_time_type)
  {
  case TIME_TYPE_YEAR:
    sprintf(buf, "%04d", tm.tm_year + 1900);
    break;
  case TIME_TYPE_MONTH:
    sprintf(buf, "%04d%02d", tm.tm_year + 1900, tm.tm_mon + 1);
    break;
  case TIME_TYPE_DAY:
    sprintf(buf, "%04d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
    break;
  case TIME_TYPE_HOUR:
    sprintf(buf, "%04d%02d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour);
    break;
  default:
    sprintf(buf, "%04d%02d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour);
    break;
  }
  
  if (swup->sw_curfileflag == NULL)
  {
    timewin_copy_string(&swup->sw_curfileflag, buf);
    swup->sw_flags = 1;
  }
  else if (strcmp(swup->sw_curfileflag, buf) != 0)
  {
    timewin_copy_string(&swup->sw_prefileflag, swup->sw_curfileflag);
    timewin_copy_string(&swup->sw_curfileflag, buf);
    swup->sw_flags = 1;
  }
  
  return swup->sw_flags;
}

/******************************************************************************/
static int timewin_copy_string(char** szDest, const char* src)
{
  int len = 0;
  if (src == 0)
  {
    return -1;
  }
  len = strlen(src) + 1;

  if (*szDest == NULL)
  {
    * szDest = (char *)malloc(len);
  }
  else if (strlen(*szDest) < len)
  {
    free(*szDest);
    * szDest = (char *)malloc(len);
    memset(*szDest, 0, len);
  }
  memcpy(* szDest, src, len);
  return 0;
}

/*******************************************************************************/

static int timewin_open_file(char *filename, FILE **fpp ){
 int rc = 0;
 sd_debug("timewin_open_file['%s'", filename);

 if ( (*fpp = fopen(filename, "a+")) == NULL){
  sd_error("failed to open file '%s'--defaulting to stderr--error='%s'",
      filename, strerror(errno));  
  *fpp = stderr;
  rc = 1;
 } 
  
 /* unbuffered mode at the filesystem level
  xxx make this configurable from the outside ?
 */
 setbuf(*fpp, NULL);  

 sd_debug("]"); 

 return(rc);

}

/****************************************************************************/

const log4c_rollingpolicy_type_t log4c_rollingpolicy_type_timewin = {
  "timewin",
  timewin_init,
  timewin_is_triggering_event,
  timewin_rollover,
  timewin_fini
};

  


7.3 init.c

#ifdef WITH_ROLLINGFILE
static const log4c_rollingpolicy_type_t * const rollingpolicy_types[] = {
  &log4c_rollingpolicy_type_sizewin,
  &log4c_rollingpolicy_type_timewin
};
static size_t nrollingpolicy_types =
  sizeof(rollingpolicy_types) / sizeof(rollingpolicy_types[0]);
#endif

rc.c

#ifdef WITH_ROLLINGFILE
/******************************************************************************/
static int rollingpolicy_load(log4c_rc_t* this, sd_domnode_t* anode)
{
  sd_domnode_t*  name  = sd_domnode_attrs_get(anode, "name");
  sd_domnode_t*  type  = sd_domnode_attrs_get(anode, "type");
  log4c_rollingpolicy_t* rpolicyp = NULL;
  
  sd_debug("rollingpolicy_load[");
  if (!name) {
  sd_error("attribute /"name/" is missing");
  return -1;
  }

  rpolicyp = log4c_rollingpolicy_get(name->value);  


  if (type){
  log4c_rollingpolicy_set_type(rpolicyp,
       log4c_rollingpolicy_type_get(type->value));
  
   if (!strcasecmp(type->value, "sizewin")){
    sd_domnode_t*  maxsize  = sd_domnode_attrs_get(anode, "maxsize");
    sd_domnode_t*  maxnum = sd_domnode_attrs_get(anode, "maxnum");
    rollingpolicy_sizewin_udata_t *sizewin_udatap = NULL;
    
    sd_debug("type='sizewin', maxsize='%s', maxnum='%s', "
         "rpolicyname='%s'",
      (maxsize && maxsize->value ? maxsize->value :"(not set)"),
      (maxnum && maxnum->value ? maxnum->value :"(not set)"),
      (name && name->value ? name->value :"(not set)"));
    /*
     * Get a new sizewin policy type and configure it.
     * Then attach it to the policy object.
     * Check to see if this policy already has a
     sw udata object. If so, leave as is except update
     the params
    */
    if ( !(sizewin_udatap = log4c_rollingpolicy_get_udata(rpolicyp))){
     sd_debug("creating new sizewin udata for this policy");
     sizewin_udatap = sizewin_make_udata();
     log4c_rollingpolicy_set_udata(rpolicyp,sizewin_udatap); 
     sizewin_udata_set_file_maxsize(sizewin_udatap, atoi(maxsize->value));
    sizewin_udata_set_max_num_files(sizewin_udatap, atoi(maxnum->value));
    }else{
     sd_debug("policy already has a sizewin udata--just updating params");
    sizewin_udata_set_file_maxsize(sizewin_udatap, atoi(maxsize->value));
    sizewin_udata_set_max_num_files(sizewin_udatap, atoi(maxnum->value));
     /* allow the policy to initialize itself */
    log4c_rollingpolicy_init(rpolicyp,
      log4c_rollingpolicy_get_rfudata(rpolicyp));
    }    
   }
   else if (!strcasecmp(type->value, "timewin")){
    sd_domnode_t*  timetype  = sd_domnode_attrs_get(anode, "timetype");
    sd_domnode_t*  maxnum = sd_domnode_attrs_get(anode, "maxnum");
    rollingpolicy_timewin_udata_t *timewin_udatap = NULL;
    
    sd_debug("type='timewin', timetype='%s', maxnum='%s', "
         "rpolicyname='%s'",
      (timetype && timetype->value ? timetype->value :"(not set)"),
      (maxnum && maxnum->value ? maxnum->value :"(not set)"),
      (name && name->value ? name->value :"(not set)"));
    /*
     * Get a new sizewin policy type and configure it.
     * Then attach it to the policy object.
     * Check to see if this policy already has a
     sw udata object. If so, leave as is except update
     the params
    */
    if ( !(timewin_udatap = log4c_rollingpolicy_get_udata(rpolicyp))){
     sd_debug("creating new sizewin udata for this policy");
     timewin_udatap = timewin_make_udata();
     log4c_rollingpolicy_set_udata(rpolicyp,timewin_udatap); 
     timewin_udata_set_file_time_type(timewin_udatap, atoi(timetype->value));
     timewin_udata_set_max_num_files(timewin_udatap, atoi(maxnum->value));
    }else{
     sd_debug("policy already has a sizewin udata--just updating params");
    timewin_udata_set_file_time_type(timewin_udatap, atoi(timetype->value));
    timewin_udata_set_max_num_files(timewin_udatap, atoi(maxnum->value));
     /* allow the policy to initialize itself */
    log4c_rollingpolicy_init(rpolicyp,
      log4c_rollingpolicy_get_rfudata(rpolicyp));
    }    
   
   }
  
  }
  sd_debug("]");

  return 0;
}
#endif

这篇关于开源日志库log4c存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/599732

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

java -jar example.jar 产生的日志输出到指定文件的方法

《java-jarexample.jar产生的日志输出到指定文件的方法》这篇文章给大家介绍java-jarexample.jar产生的日志输出到指定文件的方法,本文给大家介绍的非常详细,对大家的... 目录怎么让 Java -jar example.jar 产生的日志输出到指定文件一、方法1:使用重定向1、

C#控制台程序同步调用WebApi实现方式

《C#控制台程序同步调用WebApi实现方式》控制台程序作为Job时,需同步调用WebApi以确保获取返回结果后执行后续操作,否则会引发TaskCanceledException异常,同步处理可避免异... 目录同步调用WebApi方法Cls001类里面的写法总结控制台程序一般当作Job使用,有时候需要控制

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

nginx配置错误日志的实现步骤

《nginx配置错误日志的实现步骤》配置nginx代理过程中,如果出现错误,需要看日志,可以把nginx日志配置出来,以便快速定位日志问题,下面就来介绍一下nginx配置错误日志的实现步骤,感兴趣的可... 目录前言nginx配置错误日志总结前言在配置nginx代理过程中,如果出现错误,需要看日志,可以把

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用