Parent Directory
|
Revision Log
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(×tamp[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 |