log4c 如何使用,以及如何自定义Logout

我在使用log4c 记录日志的时候, 使用标准的dated 时打印的时间是格林威治时间 也就是比我们的时间晚了8个小时;

于是阅读源码, 依葫芦画瓢的添加了一个新的layout------------dated_local 本地时间;  于是要添加两个文件.c  和.h 文件;   文件实现不难;

主要是不太熟悉MAKEFILE的更改;  后来学习了下面的文章;http://blog.csdn.net/kingsong0816/article/details/6029863  相当不错;向作者致敬!


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);
   }
}

log4c  自定义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();
……

6.自定义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 
Spring Boot Security 自定义 logout 追加回调通常是在需要在用户注销(logout)时执行额外操作的情况。你可以通过实现 `ApplicationLogoutListener` 接口或者覆盖 `SecurityConfiguration` 类中的 `configureGlobal` 或者 `configure` 方法自定义注销过程。 首先,创建一个自定义的监听器: ```java import org.springframework.context.event.EventListener; import org.springframework.security.authentication.event.LogoutSuccessEvent; public class CustomLogoutListener { @EventListener public void handleLogoutSuccess(LogoutSuccessEvent event) { String username = (String) event.getAuthentication().getName(); System.out.println("User " + username + " has logged out successfully."); // 执行你的其他业务逻辑,如清空缓存、删除session数据等 // ... } } ``` 然后,在 Spring Boot 容器启动时注册这个监听器: ```java @Configuration public class AppConfig { @Bean public CustomLogoutListener customLogoutListener() { return new CustomLogoutListener(); } // 如果你使用的是 WebSecurityConfigurerAdapter // @Override // protected void configure(HttpSecurity http) throws Exception { // // ... // http.addLogoutSuccessHandler(customLogoutListener()); // } // 或者如果你使用的是 SecurityConfig // @Autowired // private SecurityFilterChain filterChain; // // @Override // public void configure(WebSecurity web) throws Exception { // // ... // web.logout().addLogoutSuccessHandler(customLogoutListener()); // } } ``` 这样,每当有用户成功注销时,`handleLogoutSuccess` 方法会被调用并执行相应的回调操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值