Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

logger.c File Reference

#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <asterisk/lock.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/config.h>
#include <asterisk/term.h>
#include <asterisk/cli.h>
#include <asterisk/utils.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include "asterisk.h"
#include "astconf.h"
#include <syslog.h>
#include <asterisk/logger.h>

Go to the source code of this file.

Data Structures

struct  logchannel
struct  msglist
struct  verb

Defines

#define SYSLOG_NAMES
#define SYSLOG_NLEVELS   6
#define MAX_MSG_QUEUE   200

Functions

 AST_MUTEX_DEFINE_STATIC (msglist_lock)
 AST_MUTEX_DEFINE_STATIC (loglock)
 AST_MUTEX_DEFINE_STATIC (qloglock)
void ast_queue_log (const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
int reload_logger (int rotate)
int init_logger (void)
void close_logger (void)
void ast_log (int level, const char *file, int line, const char *function, const char *fmt,...)
 Used for sending a log message. More...

void ast_verbose (const char *fmt,...)
 Send a verbose message (based on verbose level). More...

int ast_verbose_dmesg (void(*v)(const char *string, int opos, int replacelast, int complete))
int ast_register_verbose (void(*v)(const char *string, int opos, int replacelast, int complete))
int ast_unregister_verbose (void(*v)(const char *string, int opos, int replacelast, int complete))


Define Documentation

#define MAX_MSG_QUEUE   200
 

Definition at line 49 of file logger.c.

Referenced by ast_verbose().

#define SYSLOG_NAMES
 

Definition at line 33 of file logger.c.

#define SYSLOG_NLEVELS   6
 

Definition at line 45 of file logger.c.


Function Documentation

void ast_log int    level,
const char *    file,
int    line,
const char *    function,
const char *    fmt,
...   
 

Used for sending a log message.

Parameters:
level  don't need to worry about it
file  ditto
line  ditto
function  ditto
fmt  this is what is important. The format is the same as your favorite breed of printf. You know how that works, right? :-) This is the standard logger function. Probably the only way you will invoke it would be something like this: ast_log(LOG_WHATEVER, "Problem with the s Captain. We should get some more. Will d be enough?", "flux capacitor", 10); where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending on which log you wish to output to.

Definition at line 497 of file logger.c.

References __LOG_DEBUG, __LOG_EVENT, __LOG_VERBOSE, ast_console_puts(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), COLOR_BRWHITE, logchannel::console, logchannel::fileptr, LOG_EVENT, logchannel::logmask, logchannel::next, reload_logger(), logchannel::syslog, and term_color().

00498 {
00499    struct logchannel *chan;
00500    char buf[BUFSIZ];
00501    time_t t;
00502    struct tm tm;
00503    char date[256];
00504 
00505    va_list ap;
00506    
00507    if (!option_verbose && !option_debug && (level == __LOG_DEBUG)) {
00508       return;
00509    }
00510 
00511    /* begin critical section */
00512    ast_mutex_lock(&loglock);
00513 
00514    time(&t);
00515    localtime_r(&t, &tm);
00516    strftime(date, sizeof(date), dateformat, &tm);
00517 
00518    if (level == __LOG_EVENT) {
00519       va_start(ap, fmt);
00520 
00521       fprintf(eventlog, "%s asterisk[%d]: ", date, getpid());
00522       vfprintf(eventlog, fmt, ap);
00523       fflush(eventlog);
00524 
00525       va_end(ap);
00526       ast_mutex_unlock(&loglock);
00527       return;
00528    }
00529 
00530    if (logchannels) {
00531       chan = logchannels;
00532       while(chan) {
00533          if (chan->syslog && (chan->logmask & (1 << level))) {
00534             va_start(ap, fmt);
00535             ast_log_vsyslog(level, file, line, function, fmt, ap);
00536             va_end(ap);
00537          } else if ((chan->logmask & (1 << level)) && (chan->console)) {
00538             char linestr[128];
00539             char tmp1[80], tmp2[80], tmp3[80], tmp4[80];
00540 
00541             if (level != __LOG_VERBOSE) {
00542                sprintf(linestr, "%d", line);
00543                snprintf(buf, sizeof(buf), "%s %s[%ld]: %s:%s %s: ",
00544                   date,
00545                   term_color(tmp1, levels[level], colors[level], 0, sizeof(tmp1)),
00546                   (long)pthread_self(),
00547                   term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
00548                   term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
00549                   term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
00550           
00551                ast_console_puts(buf);
00552                va_start(ap, fmt);
00553                vsnprintf(buf, sizeof(buf), fmt, ap);
00554                va_end(ap);
00555                ast_console_puts(buf);
00556             }
00557          } else if ((chan->logmask & (1 << level)) && (chan->fileptr)) {
00558             snprintf(buf, sizeof(buf), "%s %s[%ld]: ", date,
00559                levels[level], (long)pthread_self());
00560             fprintf(chan->fileptr, buf);
00561             va_start(ap, fmt);
00562             vsnprintf(buf, sizeof(buf), fmt, ap);
00563             va_end(ap);
00564             fputs(buf, chan->fileptr);
00565             fflush(chan->fileptr);
00566          }
00567          chan = chan->next;
00568       }
00569    } else {
00570       /* 
00571        * we don't have the logger chain configured yet,
00572        * so just log to stdout 
00573       */
00574       if (level != __LOG_VERBOSE) {
00575          va_start(ap, fmt);
00576          vsnprintf(buf, sizeof(buf), fmt, ap);
00577          va_end(ap);
00578          fputs(buf, stdout);
00579       }
00580    }
00581 
00582    ast_mutex_unlock(&loglock);
00583    /* end critical section */
00584    if (pending_logger_reload) {
00585       reload_logger(1);
00586       ast_log(LOG_EVENT,"Rotated Logs Per SIGXFSZ\n");
00587       if (option_verbose)
00588          ast_verbose("Rotated Logs Per SIGXFSZ\n");
00589    }
00590 }

AST_MUTEX_DEFINE_STATIC qloglock   
 

AST_MUTEX_DEFINE_STATIC loglock   
 

AST_MUTEX_DEFINE_STATIC msglist_lock   
 

void ast_queue_log const char *    queuename,
const char *    callid,
const char *    agent,
const char *    event,
const char *    fmt,
...   
 

Definition at line 255 of file logger.c.

References ast_mutex_lock, and ast_mutex_unlock.

00256 {
00257    va_list ap;
00258    ast_mutex_lock(&qloglock);
00259    if (qlog) {
00260       va_start(ap, fmt);
00261       fprintf(qlog, "%ld|%s|%s|%s|%s|", (long)time(NULL), callid, queuename, agent, event);
00262       vfprintf(qlog, fmt, ap);
00263       fprintf(qlog, "\n");
00264       va_end(ap);
00265       fflush(qlog);
00266    }
00267    ast_mutex_unlock(&qloglock);
00268 }

int ast_register_verbose void(*    v)(const char *string, int opos, int replacelast, int complete)
 

Definition at line 670 of file logger.c.

References ast_mutex_lock, ast_mutex_unlock, malloc, and string.

Referenced by main().

00671 {
00672    struct msglist *m;
00673    struct verb *tmp;
00674    /* XXX Should be more flexible here, taking > 1 verboser XXX */
00675    if ((tmp = malloc(sizeof (struct verb)))) {
00676       tmp->verboser = v;
00677       ast_mutex_lock(&msglist_lock);
00678       tmp->next = verboser;
00679       verboser = tmp;
00680       m = list;
00681       while(m) {
00682          /* Send all the existing entries that we have queued (i.e. they're likely to have missed) */
00683          v(m->msg, 0, 0, 1);
00684          m = m->next;
00685       }
00686       ast_mutex_unlock(&msglist_lock);
00687       return 0;
00688    }
00689    return -1;
00690 }

int ast_unregister_verbose void(*    v)(const char *string, int opos, int replacelast, int complete)
 

Definition at line 692 of file logger.c.

References ast_mutex_lock, ast_mutex_unlock, free, and string.

00693 {
00694    int res = -1;
00695    struct verb *tmp, *tmpl=NULL;
00696    ast_mutex_lock(&msglist_lock);
00697    tmp = verboser;
00698    while(tmp) {
00699       if (tmp->verboser == v) {
00700          if (tmpl)
00701             tmpl->next = tmp->next;
00702          else
00703             verboser = tmp->next;
00704          free(tmp);
00705          break;
00706       }
00707       tmpl = tmp;
00708       tmp = tmp->next;
00709    }
00710    if (tmp)
00711       res = 0;
00712    ast_mutex_unlock(&msglist_lock);
00713    return res;
00714 }

void ast_verbose const char *    fmt,
...   
 

Send a verbose message (based on verbose level).

This works like ast_log, but prints verbose messages to the console depending on verbosity level set. ast_verbose(VERBOSE_PREFIX_3 "Whatever s is happening
", "nothing"); This will print the message to the console if the verbose level is set to a level >= 3 Note the abscence of a comma after the VERBOSE_PREFIX_3. This is important. VERBOSE_PREFIX_1 through VERBOSE_PREFIX_3 are defined.

Definition at line 592 of file logger.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, free, LOG_ERROR, LOG_VERBOSE, malloc, MAX_MSG_QUEUE, and strdup.

00593 {
00594    static char stuff[4096];
00595    static int pos = 0, opos;
00596    static int replacelast = 0, complete;
00597    struct msglist *m;
00598    struct verb *v;
00599    va_list ap;
00600    va_start(ap, fmt);
00601    ast_mutex_lock(&msglist_lock);
00602    vsnprintf(stuff + pos, sizeof(stuff) - pos, fmt, ap);
00603    opos = pos;
00604    pos = strlen(stuff);
00605    if (fmt[strlen(fmt)-1] == '\n') 
00606       complete = 1;
00607    else
00608       complete=0;
00609    if (complete) {
00610       if (msgcnt < MAX_MSG_QUEUE) {
00611          /* Allocate new structure */
00612          m = malloc(sizeof(struct msglist));
00613          msgcnt++;
00614       } else {
00615          /* Recycle the oldest entry */
00616          m = list;
00617          list = list->next;
00618          free(m->msg);
00619       }
00620       if (m) {
00621          m->msg = strdup(stuff);
00622          if (m->msg) {
00623             if (last)
00624                last->next = m;
00625             else
00626                list = m;
00627             m->next = NULL;
00628             last = m;
00629          } else {
00630             msgcnt--;
00631             ast_log(LOG_ERROR, "Out of memory\n");
00632             free(m);
00633          }
00634       }
00635    }
00636    if (verboser) {
00637       v = verboser;
00638       while(v) {
00639          v->verboser(stuff, opos, replacelast, complete);
00640          v = v->next;
00641       }
00642    } /* else
00643       fprintf(stdout, stuff + opos); */
00644 
00645    ast_log(LOG_VERBOSE, stuff);
00646 
00647    if (fmt[strlen(fmt)-1] != '\n') 
00648       replacelast = 1;
00649    else 
00650       replacelast = pos = 0;
00651    va_end(ap);
00652 
00653    ast_mutex_unlock(&msglist_lock);
00654 }

int ast_verbose_dmesg void(*    v)(const char *string, int opos, int replacelast, int complete)
 

Definition at line 656 of file logger.c.

References ast_mutex_lock, ast_mutex_unlock, and string.

00657 {
00658    struct msglist *m;
00659    ast_mutex_lock(&msglist_lock);
00660    m = list;
00661    while(m) {
00662       /* Send all the existing entries that we have queued (i.e. they're likely to have missed) */
00663       v(m->msg, 0, 0, 1);
00664       m = m->next;
00665    }
00666    ast_mutex_unlock(&msglist_lock);
00667    return 0;
00668 }

void close_logger void   
 

Definition at line 454 of file logger.c.

References ast_mutex_lock, ast_mutex_unlock, and free.

00455 {
00456    struct msglist *m, *tmp;
00457 
00458    ast_mutex_lock(&msglist_lock);
00459    m = list;
00460    while(m) {
00461       if (m->msg) {
00462          free(m->msg);
00463       }
00464       tmp = m->next;
00465       free(m);
00466       m = tmp;
00467    }
00468    list = last = NULL;
00469    msgcnt = 0;
00470    ast_mutex_unlock(&msglist_lock);
00471    return;
00472 }

int init_logger void   
 

Definition at line 422 of file logger.c.

References ast_cli_register(), ast_log(), ast_verbose(), EVENTLOG, LOG_ERROR, and LOG_EVENT.

Referenced by main().

00423 {
00424    char tmp[256];
00425 
00426    /* auto rotate if sig SIGXFSZ comes a-knockin */
00427    (void) signal(SIGXFSZ,(void *) handle_SIGXFSZ);
00428 
00429    /* register the relaod logger cli command */
00430    ast_cli_register(&reload_logger_cli);
00431    ast_cli_register(&rotate_logger_cli);
00432 
00433    /* initialize queue logger */
00434    queue_log_init();
00435 
00436    /* create the eventlog */
00437    mkdir((char *)ast_config_AST_LOG_DIR, 0755);
00438    snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG);
00439    eventlog = fopen((char *)tmp, "a");
00440    if (eventlog) {
00441       init_logger_chain();
00442       ast_log(LOG_EVENT, "Started Asterisk Event Logger\n");
00443       if (option_verbose)
00444          ast_verbose("Asterisk Event Logger Started %s\n",(char *)tmp);
00445       return 0;
00446    } else 
00447       ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
00448 
00449    /* create log channels */
00450    init_logger_chain();
00451    return -1;
00452 }

int reload_logger int    rotate
 

Definition at line 289 of file logger.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), EVENTLOG, logchannel::filename, logchannel::fileptr, LOG_ERROR, LOG_EVENT, and logchannel::next.

Referenced by ast_log(), and main().

00290 {
00291    char old[AST_CONFIG_MAX_PATH] = "";
00292    char new[AST_CONFIG_MAX_PATH];
00293    struct logchannel *f;
00294    FILE *myf;
00295 
00296    int x;
00297    ast_mutex_lock(&loglock);
00298    if (eventlog) 
00299       fclose(eventlog);
00300    else 
00301       rotate = 0;
00302    eventlog = NULL;
00303 
00304 
00305 
00306    mkdir((char *)ast_config_AST_LOG_DIR, 0755);
00307    snprintf(old, sizeof(old), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG);
00308 
00309    if(rotate) {
00310       for(x=0;;x++) {
00311          snprintf(new, sizeof(new), "%s/%s.%d", (char *)ast_config_AST_LOG_DIR, EVENTLOG,x);
00312          myf = fopen((char *)new, "r");
00313          if(myf) 
00314             fclose(myf);
00315          else
00316             break;
00317       }
00318    
00319       /* do it */
00320       if (rename(old,new))
00321          fprintf(stderr, "Unable to rename file '%s' to '%s'\n", old, new);
00322    }
00323 
00324    eventlog = fopen(old, "a");
00325 
00326    f = logchannels;
00327    while(f) {
00328       if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) {
00329          fclose(f->fileptr);
00330          f->fileptr = NULL;
00331          if(rotate) {
00332             strncpy(old, f->filename, sizeof(old) - 1);
00333    
00334             for(x=0;;x++) {
00335                snprintf(new, sizeof(new), "%s.%d", f->filename, x);
00336                myf = fopen((char *)new, "r");
00337                if (myf) {
00338                   fclose(myf);
00339                } else {
00340                   break;
00341                }
00342             }
00343        
00344             /* do it */
00345             if (rename(old,new))
00346                fprintf(stderr, "Unable to rename file '%s' to '%s'\n", old, new);
00347          }
00348       }
00349       f = f->next;
00350    }
00351 
00352    ast_mutex_unlock(&loglock);
00353 
00354    queue_log_init();
00355 
00356    if (eventlog) {
00357       init_logger_chain();
00358       ast_log(LOG_EVENT, "Restarted Asterisk Event Logger\n");
00359       if (option_verbose)
00360          ast_verbose("Asterisk Event Logger restarted\n");
00361       return 0;
00362    } else 
00363       ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
00364    init_logger_chain();
00365    pending_logger_reload = 0;
00366    return -1;
00367 }


Generated on Thu Oct 28 11:33:03 2004 for Asterisk by doxygen1.2.15