[server] / trunk / lib / logger.cxx Repository:
ViewVC logotype

View of /trunk/lib/logger.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 318 - (download) (annotate)
Thu Jul 2 09:30:15 2009 UTC (3 years, 10 months ago) by jtarlton
File size: 7242 byte(s)
reset tty colours on exit
    1 /*
    2  * Copyright (C) 2009 Dialogic Corp.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   17  * 02110-1301, USA.
   18  * Alternatively see <http://www.gnu.org/licenses/>.
   19  * Or see the LICENSE file included within the source tree.
   20  *
   21  */
   22 
   23 /*!
   24  * \file    lib/logger.cxx
   25  * \brief   Simple logger for C++ applications.
   26  * \author  John Tarlton
   27  * \version 0.1
   28  */
   29 
   30 
   31 /*----------------------------- Dependencies -------------------------------*/
   32 
   33 #include <stdlib.h>
   34 #include <string.h>
   35 #include <syslog.h>
   36 #include <sys/time.h>
   37 #include <sstream>
   38 #include <iostream>
   39 #include <iomanip>
   40 
   41 #include "logger.h"
   42 
   43 /*--------------------------------------------------------------------------*/
   44 
   45 /*
   46  * Set the default logging level.
   47  */
   48 Logger::Logger()
   49   : level_ (LOGLEVEL_NOTICE)
   50 {
   51   pthread_mutex_init(&write_mutex_, NULL);
   52 }
   53 
   54 
   55 /*
   56  * Delete all appenders.
   57  */
   58 Logger::~Logger()
   59 {
   60   std::vector<Appender*>::iterator i;
   61   for ( i = appenders_.begin(); i != appenders_.end(); ++i )
   62   {
   63     delete *i;
   64   }
   65 }
   66 
   67 
   68 /*
   69  * Attach an Appender to the logger.
   70  */
   71 void Logger::attachAppender( Logger::Appender* appender )
   72 {
   73   appenders_.push_back(appender);
   74 }
   75 
   76 
   77 /*
   78  * Validate and set the active logging level.
   79  */
   80 void Logger::setLevel( LogLevel level )
   81 {
   82   if ( (level == LOGLEVEL_EMERG) ||
   83        (level == LOGLEVEL_ALERT) ||
   84        (level == LOGLEVEL_CRIT) ||
   85        (level == LOGLEVEL_ERR) ||
   86        (level == LOGLEVEL_WARN) ||
   87        (level == LOGLEVEL_NOTICE) ||
   88        (level == LOGLEVEL_INFO) ||
   89        (level == LOGLEVEL_DEBUG) )
   90   {
   91       level_ = level;
   92   }
   93 }
   94 
   95 
   96 /*
   97  * Build a logging record and write it to the backend appenders.
   98  * Format: <TIMESTAMP><SPACE><LOGLEVEL><SPACE><MESSAGE><NEWLINE>
   99  */
  100 void Logger::write( LogLevel level, const std::string& s )
  101 {
  102   if ( (level > level_) || (level < LOGLEVEL_EMERG) )
  103   {
  104     return;
  105   }
  106 
  107   struct timeval tvbuf;
  108   gettimeofday(&tvbuf, 0);
  109 
  110   struct tm tmbuf;
  111   localtime_r(&tvbuf.tv_sec, &tmbuf);
  112 
  113   char timestamp[26 + 1];   /* YYYY-MM-DD HH:MM:SS.uuuuuu<NUL> */
  114 
  115   const char* fmt = "%Y-%m-%d %H:%M:%S";
  116   size_t len = strftime(timestamp, sizeof(timestamp)-7, fmt, &tmbuf);
  117   sprintf(&timestamp[len], ".%06ld", tvbuf.tv_usec);
  118 
  119   const char* loglevels[] = { "EMERG ", "ALERT ", "CRIT  ", "ERROR ", "WARN  ", "NOTICE", "INFO  ", "DEBUG " };
  120 
  121   std::stringstream ss;
  122   ss << timestamp << " "
  123      << loglevels[level] << " "
  124      << s << "\n";
  125 
  126   /* write the formatted message out to all appenders.
  127    */
  128   pthread_mutex_lock(&write_mutex_);
  129 
  130   std::vector<Appender*>::const_iterator i;
  131   for ( i = appenders_.begin(); i != appenders_.end(); ++i )
  132   {
  133     (*i)->write(level, ss.str());
  134   }
  135 
  136   pthread_mutex_unlock(&write_mutex_);
  137 }
  138 
  139 
  140 ///////////////////////////////////////////////////////////////////////////////
  141 
  142 /*!
  143  * ctor, if colour has been requested and the tty supports it, enable its use.
  144  */
  145 ConsoleAppender::ConsoleAppender( bool colour )
  146   : colour_term_ (false)
  147 {
  148   if ( colour )
  149   {
  150     const char* term = getenv("TERM");
  151     if ( term )
  152     {
  153       if ( !strcmp(term, "xterm") || !strcmp(term, "linux") )
  154       {
  155         colour_term_ = true;
  156       }
  157     }
  158   }
  159 }
  160 
  161 
  162 /*!
  163  * dtor, reset terminal colours.
  164  */
  165 ConsoleAppender::~ConsoleAppender()
  166 {
  167   if ( colour_term_ )
  168   {
  169     std::cerr << "\033[0m";
  170   }
  171 }
  172 
  173 
  174 /*
  175  * If enabled set the text attribute and colour.
  176  */
  177 void ConsoleAppender::textcolour( ConsoleAttr attr,
  178                                   ConsoleColour fg,
  179                                   ConsoleColour bg )
  180 {
  181   if ( colour_term_ )
  182   {
  183     std::cerr << "\033[" << attr << ';' << fg + 30 << ';' << bg + 40 << 'm';
  184   }
  185 }
  186 
  187 
  188 /*
  189  * Copy the message to stderr.
  190  */
  191 void ConsoleAppender::write( Logger::LogLevel level, const std::string& msg )
  192 {
  193   switch ( level )
  194   {
  195     case Logger::LOGLEVEL_EMERG:
  196       textcolour(BRIGHT, RED, BLACK);
  197       break;
  198     case Logger::LOGLEVEL_ALERT:
  199       textcolour(BRIGHT, RED, BLACK);
  200       break;
  201     case Logger::LOGLEVEL_CRIT:
  202       textcolour(BRIGHT, RED, BLACK);
  203       break;
  204     case Logger::LOGLEVEL_ERR:
  205       textcolour(DIM, RED, BLACK);
  206       break;
  207     case Logger::LOGLEVEL_WARN:
  208       textcolour(BRIGHT, YELLOW, BLACK);
  209       break;
  210     case Logger::LOGLEVEL_NOTICE:
  211       textcolour(BRIGHT, BLUE, BLACK);
  212       break;
  213     case Logger::LOGLEVEL_INFO:
  214       textcolour(BRIGHT, WHITE, BLACK);
  215       break;
  216     case Logger::LOGLEVEL_DEBUG:
  217       textcolour(DIM, WHITE, BLACK);
  218       break;
  219     default:
  220       break; /* unreachable */
  221   }
  222 
  223   std::cerr << msg;
  224 
  225   textcolour(DIM, WHITE, BLACK);
  226 }
  227 
  228 ///////////////////////////////////////////////////////////////////////////////
  229 
  230 /*
  231  * ctor.
  232  */
  233 FileAppender::FileAppender( const std::string& path,
  234                             const std::string& basename,
  235                             ssize_t max_size )
  236   : path_ (path),
  237     basename_ (basename),
  238     max_size_ (max_size)
  239 {
  240   ;
  241 }
  242 
  243 
  244 /*
  245  * dtor. close the file
  246  */
  247 FileAppender::~FileAppender()
  248 {
  249   fout_.close();
  250 }
  251 
  252 
  253 /*
  254  * Open a new file. The file is named by appending the current time stamp
  255  * to the base filename.
  256  *
  257  *     basename-YYYYMMDD-HHMMSS.log
  258  */
  259 void FileAppender::open()
  260 {
  261   time_t now = time(NULL);
  262   struct tm tmbuf;
  263   localtime_r(&now, &tmbuf);
  264 
  265   std::stringstream filename;
  266   filename << path_ << '/' << basename_ << '-';
  267 
  268   filename << tmbuf.tm_year + 1900;
  269   filename << std::setw(2) << std::setfill('0') << tmbuf.tm_mon + 1;
  270   filename << std::setw(2) << std::setfill('0') << tmbuf.tm_mday;
  271   filename << '-';
  272   filename << std::setw(2) << std::setfill('0') << tmbuf.tm_hour;
  273   filename << std::setw(2) << std::setfill('0') << tmbuf.tm_min;
  274   filename << std::setw(2) << std::setfill('0') << tmbuf.tm_sec;
  275   filename << ".log";
  276 
  277   fout_.open(filename.str().c_str(), std::ios::app);
  278 }
  279 
  280 
  281 /*
  282  * Close the current file and open a new one.
  283  */
  284 void FileAppender::rollover()
  285 {
  286   fout_.close();
  287   fout_.clear();
  288 
  289   open();
  290 }
  291 
  292 
  293 /*
  294  * Copy the message to a file.
  295  */
  296 void FileAppender::write( Logger::LogLevel level, const std::string& msg )
  297 {
  298   if ( !fout_.is_open() )
  299   {
  300     open();
  301   }
  302 
  303   if ( fout_.good() )
  304   {
  305     fout_ << msg;
  306     if ( level <= Logger::LOGLEVEL_NOTICE )
  307     {
  308       fout_.flush();
  309     }
  310     if ( (max_size_) && (fout_.tellp() > max_size_) )
  311     {
  312       rollover();
  313     }
  314   }
  315 }
  316 
  317 
  318 ///////////////////////////////////////////////////////////////////////////////
  319 
  320 /*
  321  * ctor, open the syslog.
  322  */
  323 SyslogAppender::SyslogAppender( const std::string& name )
  324   : name_ (name)
  325 {
  326   openlog(name_.c_str(), 0, LOG_USER);
  327 }
  328 
  329 
  330 /*!
  331  * dtor, close the syslog.
  332  */
  333 SyslogAppender::~SyslogAppender()
  334 {
  335   closelog();
  336 }
  337 
  338 
  339 /*
  340  * Write to the syslog daemon. Ignore low severity messages.
  341  */
  342 void SyslogAppender::write( Logger::LogLevel level, const std::string& msg )
  343 {
  344   if ( level <= Logger::LOGLEVEL_NOTICE )
  345   {
  346     syslog(level, "%s", msg.c_str());
  347   }
  348 }
  349 
  350 
  351 /*
  352  * vim:ts=4:set nu:
  353  */
  354 

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.8