|
|
@@ -0,0 +1,340 @@
|
|
|
+#include "qlog.h"
|
|
|
+#include <QTime>
|
|
|
+#include <QEvent>
|
|
|
+#include <QThread>
|
|
|
+#include <QCoreApplication>
|
|
|
+#include <iostream>
|
|
|
+#include <QDir>
|
|
|
+#include <QDate>
|
|
|
+#include <memory>
|
|
|
+#include <QDebug>
|
|
|
+#include <QDateTime>
|
|
|
+
|
|
|
+namespace QLOG {
|
|
|
+
|
|
|
+static const char * LevelName[6] = {"Test","Debug","Info","Warning","Critical","Fatal"};
|
|
|
+
|
|
|
+void customMessageHandler(QtMsgType type, const QMessageLogContext &context,const QString & msg)
|
|
|
+{
|
|
|
+ auto log = QLogManger::this_()->qDebugLog();
|
|
|
+ switch (type) {
|
|
|
+ //调试信息提示
|
|
|
+ case QtDebugMsg:
|
|
|
+ if (log->checkLevel(DebugMsg)) {
|
|
|
+ LogMessage(log,context.file,context.line,DebugMsg).stream() << msg ;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ //一般的warning提示
|
|
|
+ case QtWarningMsg:
|
|
|
+ if (log->checkLevel(WarningMsg)) {
|
|
|
+ LogMessage(log,context.file,context.line,WarningMsg).stream() << msg ;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ //严重错误提示
|
|
|
+ case QtCriticalMsg:
|
|
|
+ if (log->checkLevel(CriticalMsg)) {
|
|
|
+ LogMessage(log,context.file,context.line,CriticalMsg).stream() << msg ;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ //致命错误提示
|
|
|
+ case QtFatalMsg:
|
|
|
+ if (log->checkLevel(FatalMsg)) {
|
|
|
+ LogMessage(log,context.file,context.line,FatalMsg).stream() << msg ;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case QtInfoMsg :
|
|
|
+ if (log->checkLevel(InfoMsg)) {
|
|
|
+ LogMessage(log,context.file,context.line,InfoMsg).stream() << msg ;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+QLogManger::QLogManger()
|
|
|
+{
|
|
|
+ _thread.start();
|
|
|
+ auto nm = QCoreApplication::applicationName();
|
|
|
+ _baseLog.reset(new QLog(nm,STD_OUT));
|
|
|
+ _baseLog->moveToThread(&_thread);
|
|
|
+ _qtLog.reset(new QLog("qtdebug",STD_OUT));
|
|
|
+ _qtLog->moveToThread(&_thread);
|
|
|
+ _logs.insert(nm,_baseLog);
|
|
|
+ _logs.insert("qtdebug",_qtLog);
|
|
|
+ connect(this,&QLogManger::updateSavePath,_baseLog.data(),&QLog::restLog,Qt::QueuedConnection);
|
|
|
+ connect(this,&QLogManger::updateSavePath,_qtLog.data(),&QLog::restLog,Qt::QueuedConnection);
|
|
|
+ setSaveFilePath(QDir::homePath() + "/qlog");
|
|
|
+}
|
|
|
+
|
|
|
+QLogManger * QLogManger::this_()
|
|
|
+{
|
|
|
+ static QLogManger logManger;
|
|
|
+ return &logManger;
|
|
|
+}
|
|
|
+
|
|
|
+QLogManger::~QLogManger()
|
|
|
+{
|
|
|
+ _thread.quit();
|
|
|
+ _thread.wait(1000);
|
|
|
+ if(_thread.isRunning()){
|
|
|
+ _thread.terminate();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool QLogManger::setSaveFilePath(const QString & path)
|
|
|
+{
|
|
|
+ QDir dir(path);
|
|
|
+ if(dir.exists() || dir.mkpath(dir.absolutePath())) {
|
|
|
+ QFileInfo info(path);
|
|
|
+ if(info.isWritable()){
|
|
|
+ path_ = dir.absolutePath();
|
|
|
+ emit updateSavePath();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+QLog * QLogManger::enbleQtMessage()
|
|
|
+{
|
|
|
+ qInstallMessageHandler(customMessageHandler);
|
|
|
+ return _qtLog.data();
|
|
|
+}
|
|
|
+
|
|
|
+QLog * QLogManger::getLog(const QString & name)
|
|
|
+{
|
|
|
+ _locker.lockForRead();
|
|
|
+ auto log = _logs.value(name);
|
|
|
+ _locker.unlock();
|
|
|
+ if(log.isNull()){
|
|
|
+ _locker.lockForWrite();
|
|
|
+ log = _logs.value(name);
|
|
|
+ if(log.isNull()){
|
|
|
+ log.reset(new QLog(name));
|
|
|
+ log->moveToThread(&_thread);
|
|
|
+ connect(this,&QLogManger::updateSavePath,log.data(),&QLog::restLog,Qt::QueuedConnection);
|
|
|
+ _logs.insert(name,log);
|
|
|
+ }
|
|
|
+ _locker.unlock();
|
|
|
+ }
|
|
|
+ return log.data();
|
|
|
+}
|
|
|
+
|
|
|
+class LogEvent : public QEvent
|
|
|
+{
|
|
|
+public:
|
|
|
+ LogEvent(QString && str,LogLevel lv): QEvent(eventType),level(lv),str_(str) {}
|
|
|
+ ~LogEvent() {}
|
|
|
+
|
|
|
+ const QString & getString() const {return str_;}
|
|
|
+
|
|
|
+ static QEvent::Type eventType;
|
|
|
+ LogLevel level;
|
|
|
+private:
|
|
|
+ QString str_;
|
|
|
+};
|
|
|
+
|
|
|
+QEvent::Type LogEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
|
|
|
+
|
|
|
+class UpEventOutStatus : public QEvent
|
|
|
+{
|
|
|
+public:
|
|
|
+ UpEventOutStatus(OutState state): QEvent(eventType),state(state) {}
|
|
|
+ ~UpEventOutStatus() {}
|
|
|
+
|
|
|
+
|
|
|
+ static QEvent::Type eventType;
|
|
|
+ OutState state;
|
|
|
+};
|
|
|
+
|
|
|
+QEvent::Type UpEventOutStatus::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
|
|
|
+
|
|
|
+LogMessage::LogMessage(QLog * log,const char * file, int line,LogLevel level) : log(log), ts(&str_),level_(level)
|
|
|
+{
|
|
|
+ if(log == nullptr || level < log->level) return;
|
|
|
+ if(log->writeTime){
|
|
|
+ ts << "[" << QTime::currentTime().toString("hh:mm:ss.zzz") << "]:";
|
|
|
+ }
|
|
|
+ if(log->writeFileInfo) {
|
|
|
+ ts << "[@ " << file << " : " << line << "]:";
|
|
|
+ }
|
|
|
+ if(log->writeLevel){
|
|
|
+ ts << "[" << LevelName[level] << "]:";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+LogMessage::LogMessage(QLog * log,LogLevel level): log(log), ts(&str_),level_(level)
|
|
|
+{
|
|
|
+ if(log == nullptr || level < log->level) return;
|
|
|
+ if(log->writeTime){
|
|
|
+ ts << "[" << QTime::currentTime().toString("hh:mm:ss.zzz") << "]:";
|
|
|
+ }
|
|
|
+ if(log->writeFileInfo) {
|
|
|
+ ts << "[@ ]:";
|
|
|
+ }
|
|
|
+ if(log->writeLevel){
|
|
|
+ ts << "[" << LevelName[level] << "]:";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+LogMessage::~LogMessage()
|
|
|
+{
|
|
|
+ if (log != nullptr && level_ >= log->level ) {
|
|
|
+ if(log->writeEndLine)
|
|
|
+ ts << "\r\n";
|
|
|
+ ts.setDevice(nullptr);
|
|
|
+ QCoreApplication::postEvent(log,new LogEvent(std::move(str_),level_));
|
|
|
+ if (level_ == FatalMsg) {
|
|
|
+ QCoreApplication::exit(-1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+QLog::QLog(const QString & name, OutState state)
|
|
|
+ : QObject(nullptr),state_(state),file_(nullptr),_name(name)
|
|
|
+{
|
|
|
+ level = TestMsg;
|
|
|
+ writeTime = true;
|
|
|
+ writeFileInfo = true;
|
|
|
+ writeLevel = true;
|
|
|
+ writeEndLine = true;
|
|
|
+ fileCreateType = DayOne;
|
|
|
+ ts_.setDevice(nullptr);
|
|
|
+ _fileCreateId = -1;
|
|
|
+}
|
|
|
+
|
|
|
+QLog::~QLog()
|
|
|
+{
|
|
|
+ releaseLogFile();
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void QLog::setOutState(OutState outState)
|
|
|
+{
|
|
|
+ QCoreApplication::postEvent(this,new UpEventOutStatus(outState));
|
|
|
+}
|
|
|
+
|
|
|
+void QLog::restLog()
|
|
|
+{
|
|
|
+ if(state_ == File){
|
|
|
+ releaseLogFile();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void QLog::releaseLogFile()
|
|
|
+{
|
|
|
+ ts_.setDevice(nullptr);
|
|
|
+ if(file_){
|
|
|
+ file_->close();
|
|
|
+ delete file_;
|
|
|
+ file_ = nullptr;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void QLog::customEvent(QEvent * event)
|
|
|
+{
|
|
|
+ if(event->type() == UpEventOutStatus::eventType){
|
|
|
+ UpEventOutStatus * ev = static_cast<UpEventOutStatus *>(event);
|
|
|
+ if(state_ != ev->state) {
|
|
|
+ state_ = ev->state;
|
|
|
+ releaseLogFile();
|
|
|
+
|
|
|
+ }
|
|
|
+ } else if (event->type() == LogEvent::eventType) {
|
|
|
+ LogEvent * ev = static_cast<LogEvent *>(event);
|
|
|
+ if(ev->level >= level) {
|
|
|
+ switch (state_) {
|
|
|
+ case STD_OUT :{
|
|
|
+ if(file_ == nullptr){
|
|
|
+ file_ = new QFile(this);
|
|
|
+ file_->open(1,QFile::Append);
|
|
|
+ ts_.setDevice(file_);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case STD_ERROR:{
|
|
|
+ if(file_ == nullptr){
|
|
|
+ if(file_ == nullptr){
|
|
|
+ file_ = new QFile(this);
|
|
|
+ file_->open(2,QFile::Append);
|
|
|
+ ts_.setDevice(file_);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case File : {
|
|
|
+ if(file_){
|
|
|
+ int id = _fileCreateId;
|
|
|
+ switch (fileCreateType) {
|
|
|
+ case DayOne: {
|
|
|
+ id = QDate::currentDate().day();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case HourOne:
|
|
|
+ id = QTime::currentTime().hour();
|
|
|
+ break;
|
|
|
+ case MonthOne:
|
|
|
+ id = QDate::currentDate().month();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ id = _fileCreateId;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(id != _fileCreateId)
|
|
|
+ releaseLogFile();
|
|
|
+ }
|
|
|
+ if(file_ == nullptr){
|
|
|
+ QString fname = QLogManger::this_()->getSaveFilePath() + "/" + _name;
|
|
|
+ switch (fileCreateType) {
|
|
|
+ case OneStartOne:{
|
|
|
+ auto pid = QCoreApplication::applicationPid();
|
|
|
+ fname += "_";
|
|
|
+ fname += QDateTime::currentDateTime().toString("yyyy-MM-dd.hh-mm-ss.zzz");
|
|
|
+ fname += "_";
|
|
|
+ fname += QString::number(pid);
|
|
|
+ _fileCreateId = 0;
|
|
|
+ }
|
|
|
+ case DayOne: {
|
|
|
+ auto dt = QDate::currentDate();
|
|
|
+ fname += "_";
|
|
|
+ fname += dt.toString("yyyy-MM-dd");
|
|
|
+ _fileCreateId = dt.day();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case HourOne:{
|
|
|
+ auto dt = QDateTime::currentDateTime();
|
|
|
+ fname += "_";
|
|
|
+ fname += dt.toString("yyyy-MM-dd.hh");
|
|
|
+ _fileCreateId = dt.time().hour();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MonthOne:{
|
|
|
+ auto dt = QDate::currentDate();
|
|
|
+ fname += "_";
|
|
|
+ fname += dt.toString("yyyy-MM");
|
|
|
+ _fileCreateId = dt.month();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ fname += ".logs";
|
|
|
+ file_ = new QFile(fname,this);
|
|
|
+ file_->open(QFile::Append);
|
|
|
+ ts_.setDevice(file_);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (ts_.device() != nullptr) {
|
|
|
+ ts_ << ev->getString();
|
|
|
+ ts_.flush();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ event->accept();
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+}//namespace QLOG
|