00001 /**************************************************************** 00002 * Vidalia is distributed under the following license: 00003 * 00004 * Copyright (C) 2007, Matt Edman, Justin Hipple 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 ****************************************************************/ 00021 00022 /** 00023 * \file log.cpp 00024 * \version $Id: log.cpp 1649 2007-02-24 18:33:17Z edmanm $ 00025 * \brief Debug message logging 00026 */ 00027 00028 #include <QDateTime> 00029 #include <QTextStream> 00030 00031 #include "log.h" 00032 00033 /** Open log files for appending as write-only text. */ 00034 #define LOGFILE_MODE \ 00035 (QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text) 00036 /** Format for log message timestamps. */ 00037 #define TIMESTAMP_FMT "MMM dd HH:mm:ss.zzz" 00038 00039 00040 /** Default constructor. Logs at level Notice by default. */ 00041 Log::Log() 00042 { 00043 _logLevel = Notice; 00044 } 00045 00046 /** Destructor. Closes the log file. */ 00047 Log::~Log() 00048 { 00049 close(); 00050 } 00051 00052 /** Returns a list of strings representing available log levels. */ 00053 QStringList 00054 Log::logLevels() 00055 { 00056 return (QStringList() << "debug" << "info" << "notice" 00057 << "warn" << "error"); 00058 } 00059 00060 /** Sets the current log level to <b>level</b>. If <b>level</b> is Off, then 00061 * the log file will be closed as well. If <b>level</b> is Unknown, no change 00062 * to the current log level is made. */ 00063 void 00064 Log::setLogLevel(LogLevel level) 00065 { 00066 if (level >= Debug && level < Unknown) 00067 _logLevel = level; 00068 if (level == Off) 00069 _logFile.close(); 00070 } 00071 00072 /** Opens <b>file</b> for appending, to which log messages will be written. */ 00073 bool 00074 Log::open(FILE *file) 00075 { 00076 if (_logFile.isOpen()) 00077 close(); 00078 00079 _logFile.open(file, LOGFILE_MODE); 00080 return isOpen(); 00081 } 00082 00083 /** Opens <b>file</b> for appending, to which log messages will be written. */ 00084 bool 00085 Log::open(QString file) 00086 { 00087 if (_logFile.isOpen()) 00088 close(); 00089 00090 _logFile.setFileName(file); 00091 _logFile.open(LOGFILE_MODE); 00092 return isOpen(); 00093 } 00094 00095 /** Flushes any outstanding log messages and closes the log file. */ 00096 void 00097 Log::close() 00098 { 00099 if (_logFile.isOpen()) { 00100 _logFile.flush(); 00101 _logFile.close(); 00102 } 00103 } 00104 00105 /** Creates a log message with severity <b>level</b> and initial message 00106 * contents <b>message</b>. The log message can be appended to until the 00107 * returned LogMessage's destructor is called, at which point the complete 00108 * message is written to the log file. */ 00109 inline Log::LogMessage 00110 Log::log(LogLevel level) 00111 { 00112 if (level < _logLevel) 00113 return LogMessage(level, 0); 00114 return LogMessage(level, &_logFile); 00115 } 00116 00117 /** Creates a log message with severity <b>level</b>. The log message can be 00118 * appended to until the returned LogMessage's destructor is called, at 00119 * which point the complete message is written to the log file. */ 00120 Log::LogMessage 00121 Log::log(LogLevel level, QString msg) 00122 { 00123 return log(level) << msg; 00124 } 00125 00126 /** Returns a string description of the given LogLevel <b>level</b>. */ 00127 inline QString 00128 Log::logLevelToString(LogLevel level) 00129 { 00130 switch (level) { 00131 case Debug: return "debug"; 00132 case Info: return "info"; 00133 case Notice: return "notice"; 00134 case Warn: return "warn"; 00135 case Error: return "error"; 00136 case Off: return "off"; 00137 default: return "unknown"; 00138 } 00139 } 00140 00141 /** Returns a LogLevel for the level given by <b>str</b>, or Unknown if the 00142 * given string does not represent a valid LogLevel value. */ 00143 Log::LogLevel 00144 Log::stringToLogLevel(QString str) 00145 { 00146 str = str.toLower(); 00147 if (str == "debug") 00148 return Debug; 00149 else if (str == "info") 00150 return Info; 00151 else if (str == "notice") 00152 return Notice; 00153 else if (str == "warn") 00154 return Warn; 00155 else if (str == "error") 00156 return Error; 00157 else if (str == "off") 00158 return Off; 00159 return Unknown; 00160 } 00161 00162 /** Returns a formatted log message, prefixed with a timestamp and the log 00163 * message severity level. */ 00164 inline QString 00165 Log::LogMessage::toString() const 00166 { 00167 QString msg = QDateTime::currentDateTime().toString(TIMESTAMP_FMT); 00168 msg.append(" [" + Log::logLevelToString(stream->type) + "] "); 00169 msg.append(stream->buf); 00170 return msg; 00171 } 00172 00173 /** Destructor. Writes the buffered log message out to the log file specified 00174 * in the constructor. */ 00175 Log::LogMessage::~LogMessage() 00176 { 00177 if (!--stream->ref) { 00178 if (stream->out && !stream->buf.isEmpty()) { 00179 QTextStream log(stream->out); 00180 log << toString() << endl; 00181 log.flush(); 00182 } 00183 delete stream; 00184 } 00185 } 00186