Vidalia  0.2.17
Log.cpp
Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
00007 **  including this file, may be copied, modified, propagated, or distributed 
00008 **  except according to the terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file Log.cpp
00013 ** \brief Debug message logging
00014 */
00015 
00016 #include "Log.h"
00017 
00018 #include <QDateTime>
00019 #include <QTextStream>
00020 
00021 /** Open log files for appending as write-only text. */
00022 #define LOGFILE_MODE  \
00023   (QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text)
00024 /** Format for log message timestamps. */
00025 #define TIMESTAMP_FMT   "MMM dd HH:mm:ss.zzz"
00026 
00027 
00028 /** Default constructor. Logs at level Notice by default. */
00029 Log::Log()
00030 {
00031   _logLevel = Notice;
00032 }
00033 
00034 /** Destructor. Closes the log file. */
00035 Log::~Log()
00036 {
00037   close();
00038 }
00039 
00040 /** Returns a list of strings representing available log levels. */
00041 QStringList
00042 Log::logLevels()
00043 {
00044   return (QStringList() << "debug" << "info" << "notice" 
00045                         << "warn" << "error");
00046 }
00047 
00048 /** Sets the current log level to <b>level</b>. If <b>level</b> is Off, then
00049  * the log file will be closed as well. If <b>level</b> is Unknown, no change
00050  * to the current log level is made. */
00051 void
00052 Log::setLogLevel(LogLevel level)
00053 {
00054   if (level >= Debug && level < Unknown)
00055     _logLevel = level;
00056   if (level == Off)
00057     _logFile.close();
00058 }
00059 
00060 /** Opens <b>file</b> for appending, to which log messages will be written. */
00061 bool
00062 Log::open(FILE *file)
00063 {
00064   if (_logFile.isOpen())
00065     close();
00066 
00067   _logFile.open(file, LOGFILE_MODE);
00068   return isOpen();
00069 }
00070 
00071 /** Opens <b>file</b> for appending, to which log messages will be written. */
00072 bool
00073 Log::open(QString file)
00074 {
00075   if (_logFile.isOpen())
00076     close();
00077 
00078   _logFile.setFileName(file);
00079   _logFile.open(LOGFILE_MODE);
00080   return isOpen();
00081 }
00082 
00083 /** Flushes any outstanding log messages and closes the log file. */
00084 void
00085 Log::close()
00086 {
00087   if (_logFile.isOpen()) {
00088     _logFile.flush();
00089     _logFile.close();
00090   }
00091 }
00092 
00093 /** Creates a log message with severity <b>level</b> and initial message
00094  * contents <b>message</b>. The log message can be appended to until the
00095  * returned LogMessage's destructor is called, at which point the complete
00096  * message is written to the log file. */
00097 inline Log::LogMessage
00098 Log::log(LogLevel level)
00099 {
00100   if (level < _logLevel)
00101     return LogMessage(level, 0);
00102   return LogMessage(level, &_logFile);
00103 }
00104 
00105 /** Creates a log message with severity <b>level</b>. The log message can be
00106  * appended to until the returned LogMessage's destructor is called, at
00107  * which point the complete message is written to the log file. */
00108 Log::LogMessage
00109 Log::log(LogLevel level, QString msg)
00110 {
00111   return log(level) << msg;
00112 }
00113 
00114 /** Returns a string description of the given LogLevel <b>level</b>. */
00115 inline QString
00116 Log::logLevelToString(LogLevel level)
00117 {
00118   switch (level) {
00119     case Debug:   return "debug";
00120     case Info:    return "info";
00121     case Notice:  return "notice";
00122     case Warn:    return "warn";
00123     case Error:   return "error";
00124     case Off:     return "off";
00125     default:      return "unknown";
00126   }
00127 }
00128 
00129 /** Returns a LogLevel for the level given by <b>str</b>, or Unknown if the
00130  * given string does not represent a valid LogLevel value. */
00131 Log::LogLevel
00132 Log::stringToLogLevel(QString str)
00133 {
00134   str = str.toLower();
00135   if (str == "debug")
00136     return Debug;
00137   else if (str == "info")
00138     return Info;
00139   else if (str == "notice")
00140     return Notice;
00141   else if (str == "warn")
00142     return Warn;
00143   else if (str == "error")
00144     return Error;
00145   else if (str == "off")
00146     return Off;
00147   return Unknown;
00148 }
00149 
00150 /** Returns a formatted log message, prefixed with a timestamp and the log
00151  * message severity level. */
00152 inline QString
00153 Log::LogMessage::toString() const
00154 {
00155   QString msg = QDateTime::currentDateTime().toString(TIMESTAMP_FMT);
00156   msg.append(" [" + Log::logLevelToString(stream->type) + "] ");
00157   msg.append(stream->buf);
00158   return msg;
00159 }
00160 
00161 /** Destructor. Writes the buffered log message out to the log file specified
00162  * in the constructor. */
00163 Log::LogMessage::~LogMessage()
00164 {
00165   if (!--stream->ref) {
00166     if (stream->out && !stream->buf.isEmpty()) {
00167       QTextStream log(stream->out);
00168       log << toString() << endl;
00169       log.flush();
00170     }
00171     delete stream;
00172   }
00173 }
00174