2013-07-12 127 views
1

夥計們,我假設按類型來劃分,例如警告和信息日誌應該被保存在其他文件...以下是QXmpp庫的類QXmppLogger,它保存所有將日誌類型記錄到一個文件中,但我必須按照前面所述的方式完成它。任何人都可以指導我通過如何編寫自己的日誌類

PS 我不能更改QXmppLogger類!

QXmppLogger.h

#ifndef QXMPPLOGGER_H 
#define QXMPPLOGGER_H 

#include <QObject> 

#include "QXmppGlobal.h" 

#ifdef QXMPP_LOGGABLE_TRACE 
#define qxmpp_loggable_trace(x) QString("%1(0x%2) %3").arg(metaObject()->className(), QString::number(reinterpret_cast<qint64>(this), 16), x) 
#else 
#define qxmpp_loggable_trace(x) (x) 
#endif 

class QXmppLoggerPrivate; 

/// \brief The QXmppLogger class represents a sink for logging messages. 
/// 
/// \ingroup Core 

class QXMPP_EXPORT QXmppLogger : public QObject 
{ 
    Q_OBJECT 
    Q_ENUMS(LoggingType) 
    Q_FLAGS(MessageType MessageTypes) 
    Q_PROPERTY(QString logFilePath READ logFilePath WRITE setLogFilePath) 
    Q_PROPERTY(LoggingType loggingType READ loggingType WRITE setLoggingType) 
    Q_PROPERTY(MessageTypes messageTypes READ messageTypes WRITE setMessageTypes) 

public: 
    /// This enum describes how log message are handled. 
    enum LoggingType 
    { 
     NoLogging = 0,  ///< Log messages are discarded 
     FileLogging = 1, ///< Log messages are written to a file 
     StdoutLogging = 2, ///< Log messages are written to the standard output 
     SignalLogging = 4, ///< Log messages are emitted as a signal 
    }; 

    /// This enum describes a type of log message. 
    enum MessageType 
    { 
     NoMessage = 0,   ///< No message type 
     DebugMessage = 1,  ///< Debugging message 
     InformationMessage = 2, ///< Informational message 
     WarningMessage = 4,  ///< Warning message 
     ReceivedMessage = 8, ///< Message received from server 
     SentMessage = 16,  ///< Message sent to server 
     AnyMessage = 31,  ///< Any message type 
    }; 
    Q_DECLARE_FLAGS(MessageTypes, MessageType) 

    QXmppLogger(QObject *parent = 0); 
    ~QXmppLogger(); 

    static QXmppLogger* getLogger(); 

    QXmppLogger::LoggingType loggingType(); 
    void setLoggingType(QXmppLogger::LoggingType type); 

    QString logFilePath(); 
    void setLogFilePath(const QString &path); 

    QXmppLogger::MessageTypes messageTypes(); 
    void setMessageTypes(QXmppLogger::MessageTypes types); 

public slots: 
    virtual void setGauge(const QString &gauge, double value); 
    virtual void updateCounter(const QString &counter, qint64 amount); 

    void log(QXmppLogger::MessageType type, const QString& text); 
    void reopen(); 

signals: 
    /// This signal is emitted whenever a log message is received. 
    void message(QXmppLogger::MessageType type, const QString &text); 

private: 
    static QXmppLogger* m_logger; 
    QXmppLoggerPrivate *d; 
}; 

/// \brief The QXmppLoggable class represents a source of logging messages. 
/// 
/// \ingroup Core 

class QXMPP_EXPORT QXmppLoggable : public QObject 
{ 
    Q_OBJECT 

public: 
    QXmppLoggable(QObject *parent = 0); 

protected: 
    /// \cond 
    virtual void childEvent(QChildEvent *event); 
    /// \endcond 

    /// Logs a debugging message. 
    /// 
    /// \param message 

    void debug(const QString &message) 
    { 
     emit logMessage(QXmppLogger::DebugMessage, qxmpp_loggable_trace(message)); 
    } 

    /// Logs an informational message. 
    /// 
    /// \param message 

    void info(const QString &message) 
    { 
     emit logMessage(QXmppLogger::InformationMessage, qxmpp_loggable_trace(message)); 
    } 

    /// Logs a warning message. 
    /// 
    /// \param message 

    void warning(const QString &message) 
    { 
     emit logMessage(QXmppLogger::WarningMessage, qxmpp_loggable_trace(message)); 
    } 

    /// Logs a received packet. 
    /// 
    /// \param message 

    void logReceived(const QString &message) 
    { 
     emit logMessage(QXmppLogger::ReceivedMessage, qxmpp_loggable_trace(message)); 
    } 

    /// Logs a sent packet. 
    /// 
    /// \param message 

    void logSent(const QString &message) 
    { 
     emit logMessage(QXmppLogger::SentMessage, qxmpp_loggable_trace(message)); 
    } 

signals: 
    /// Sets the given \a gauge to \a value. 
    void setGauge(const QString &gauge, double value); 

    /// This signal is emitted to send logging messages. 
    void logMessage(QXmppLogger::MessageType type, const QString &msg); 

    /// Updates the given \a counter by \a amount. 
    void updateCounter(const QString &counter, qint64 amount = 1); 
}; 

Q_DECLARE_OPERATORS_FOR_FLAGS(QXmppLogger::MessageTypes) 
    #endif // QXMPPLOGGER_H 

這裏是QXmppLogger.cpp

#include <iostream> 

#include <QChildEvent> 
#include <QDateTime> 
#include <QFile> 
#include <QMetaType> 
#include <QTextStream> 

#include "QXmppLogger.h" 

QXmppLogger* QXmppLogger::m_logger = 0; 

static const char *typeName(QXmppLogger::MessageType type) 
{ 
    switch (type) 
    { 
    case QXmppLogger::DebugMessage: 
     return "DEBUG"; 
    case QXmppLogger::InformationMessage: 
     return "INFO"; 
    case QXmppLogger::WarningMessage: 
     return "WARNING"; 
    case QXmppLogger::ReceivedMessage: 
     return "RECEIVED"; 
    case QXmppLogger::SentMessage: 
     return "SENT"; 
    default: 
     return ""; 
    } 
} 

static QString formatted(QXmppLogger::MessageType type, const QString& text) 
{ 
    return QDateTime::currentDateTime().toString() + " " + 
     QString::fromLatin1(typeName(type)) + " " + 
     text; 
} 

static void relaySignals(QXmppLoggable *from, QXmppLoggable *to) 
{ 
    QObject::connect(from, SIGNAL(logMessage(QXmppLogger::MessageType,QString)), 
        to, SIGNAL(logMessage(QXmppLogger::MessageType,QString))); 
    QObject::connect(from, SIGNAL(setGauge(QString,double)), 
        to, SIGNAL(setGauge(QString,double))); 
    QObject::connect(from, SIGNAL(updateCounter(QString,qint64)), 
        to, SIGNAL(updateCounter(QString,qint64))); 
} 

/// Constructs a new QXmppLoggable. 
/// 
/// \param parent 

QXmppLoggable::QXmppLoggable(QObject *parent) 
    : QObject(parent) 
{ 
    QXmppLoggable *logParent = qobject_cast<QXmppLoggable*>(parent); 
    if (logParent) { 
     relaySignals(this, logParent); 
    } 
} 

/// \cond 
void QXmppLoggable::childEvent(QChildEvent *event) 
{ 
    QXmppLoggable *child = qobject_cast<QXmppLoggable*>(event->child()); 
    if (!child) 
     return; 

    if (event->added()) { 
     relaySignals(child, this); 
    } else if (event->removed()) { 
     disconnect(child, SIGNAL(logMessage(QXmppLogger::MessageType,QString)), 
       this, SIGNAL(logMessage(QXmppLogger::MessageType,QString))); 
     disconnect(child, SIGNAL(setGauge(QString,double)), 
       this, SIGNAL(setGauge(QString,double))); 
     disconnect(child, SIGNAL(updateCounter(QString,qint64)), 
       this, SIGNAL(updateCounter(QString,qint64))); 
    } 
} 
/// \endcond 

class QXmppLoggerPrivate 
{ 
public: 
    QXmppLoggerPrivate(QXmppLogger *qq); 

    QXmppLogger::LoggingType loggingType; 
    QFile *logFile; 
    QString logFilePath; 
    QXmppLogger::MessageTypes messageTypes; 

private: 
    QXmppLogger *q; 
}; 

QXmppLoggerPrivate::QXmppLoggerPrivate(QXmppLogger *qq) 
    : loggingType(QXmppLogger::NoLogging), 
    logFile(0), 
    logFilePath("QXmppClientLog.log"), 
    messageTypes(QXmppLogger::AnyMessage), 
    q(qq) 
{ 
} 

/// Constructs a new QXmppLogger. 
/// 
/// \param parent 

QXmppLogger::QXmppLogger(QObject *parent) 
    : QObject(parent) 
{ 
    d = new QXmppLoggerPrivate(this); 

    // make it possible to pass QXmppLogger::MessageType between threads 
    qRegisterMetaType<QXmppLogger::MessageType>("QXmppLogger::MessageType"); 
} 

QXmppLogger::~QXmppLogger() 
{ 
    delete d; 
} 

/// Returns the default logger. 
/// 

QXmppLogger* QXmppLogger::getLogger() 
{ 
    if(!m_logger) 
     m_logger = new QXmppLogger(); 

    return m_logger; 
} 

/// Returns the handler for logging messages. 
/// 

QXmppLogger::LoggingType QXmppLogger::loggingType() 
{ 
    return d->loggingType; 
} 

/// Sets the handler for logging messages. 
/// 
/// \param type 

void QXmppLogger::setLoggingType(QXmppLogger::LoggingType type) 
{ 
    if (d->loggingType != type) { 
     d->loggingType = type; 
     reopen(); 
    } 
} 

/// Returns the types of messages to log. 
/// 

QXmppLogger::MessageTypes QXmppLogger::messageTypes() 
{ 
    return d->messageTypes; 
} 

/// Sets the types of messages to log. 
/// 
/// \param types 

void QXmppLogger::setMessageTypes(QXmppLogger::MessageTypes types) 
{ 
    d->messageTypes = types; 
} 

/// Add a logging message. 
/// 
/// \param type 
/// \param text 

void QXmppLogger::log(QXmppLogger::MessageType type, const QString& text) 
{ 
    // filter messages 
    if (!d->messageTypes.testFlag(type)) 
     return; 

    switch(d->loggingType) 
    { 
    case QXmppLogger::FileLogging: 
     if (!d->logFile) { 
      d->logFile = new QFile(d->logFilePath); 
      d->logFile->open(QIODevice::WriteOnly | QIODevice::Append); 
     } 
     QTextStream(d->logFile) << formatted(type, text) << "\n"; 
     break; 
    case QXmppLogger::StdoutLogging: 
     std::cout << qPrintable(formatted(type, text)) << std::endl; 
     break; 
    case QXmppLogger::SignalLogging: 
     emit message(type, text); 
     break; 
    default: 
     break; 
    } 
} 

/// Sets the given \a gauge to \a value. 
/// 
/// NOTE: the base implementation does nothing. 

void QXmppLogger::setGauge(const QString &gauge, double value) 
{ 
    Q_UNUSED(gauge); 
    Q_UNUSED(value); 
} 

/// Updates the given \a counter by \a amount. 
/// 
/// NOTE: the base implementation does nothing. 

void QXmppLogger::updateCounter(const QString &counter, qint64 amount) 
{ 
    Q_UNUSED(counter); 
    Q_UNUSED(amount); 
} 

/// Returns the path to which logging messages should be written. 
/// 
/// \sa loggingType() 

QString QXmppLogger::logFilePath() 
{ 
    return d->logFilePath; 
} 

/// Sets the path to which logging messages should be written. 
/// 
/// \param path 
/// 
/// \sa setLoggingType() 

void QXmppLogger::setLogFilePath(const QString &path) 
{ 
    if (d->logFilePath != path) { 
     d->logFilePath = path; 
     reopen(); 
    } 
} 

/// If logging to a file, causes the file to be re-opened. 
/// 

void QXmppLogger::reopen() 
{ 
    if (d->logFile) { 
     delete d->logFile; 
     d->logFile = 0; 
    } 
} 

回答

1

注意QXmppLogger::SignalLogging選項。如果它被設置,對象將發出信號而不是寫入文件message(type, text);。你可以連接到這個信號,並用typetext做任何你想做的事情。

相關問題