-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTyLogger.h
More file actions
156 lines (143 loc) · 3.15 KB
/
TyLogger.h
File metadata and controls
156 lines (143 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#ifndef TY_LOGGER_HEADER
#define TY_LOGGER_HEADER
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QTextStream>
#include <QDate>
#include <QDateTime>
#include <QMutex>
#include <QQueue>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
class TyLogger
{
private:
TyLogger()
{
//writeRunning = 0;
createLogFile();
}
TyLogger(const TyLogger&) = delete;
TyLogger& operator=(const TyLogger&) = delete;
public:
~TyLogger()
{
writeFuture.cancel();
writeFuture.waitForFinished();
file.close();
}
void write()
{
//if (!writeRunning.testAndSetAcquire(0, 1))
//{
// //qInfo() << "write log has running queue";
// return;
//}
while (true)
{
QMutexLocker locker(&mutex);
if (queue.isEmpty()) break;
const auto msg = queue.dequeue();
// 当日期跨度后相应的更新日志文件名
if (!isCurrentLogFile()) {
file.close();
createLogFile();
}
if (file.isOpen()) {
QTextStream stream(&file);
// 设置编码为UTF-8
stream.setCodec("UTF-8");
stream << msg << endl;
}
}
//// 重置标志允许write在QtConcurrent::run中运行
//writeRunning.store(0);
}
static void customMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
QString level;
switch (type)
{
case QtDebugMsg:
level = "DEBUG";
break;
case QtWarningMsg:
level = "WARN";
break;
case QtCriticalMsg:
level = "ERROR";
break;
case QtFatalMsg:
level = "FATAL";
break;
case QtInfoMsg:
level = "INFO";
break;
default:
level = "UNKN ";
break;
}
#if _DEBUG
auto fileName = QFileInfo(context.file).fileName();
QString formattedMessage = QString("[%1 %3:%4 %2] %5")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"))
.arg(level)
.arg(fileName)
.arg(context.line)
.arg(msg);
#else
QString formattedMessage = QString("[%1 %2] %5")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"))
.arg(level)
.arg(msg);
#endif
// 输出到控制台
QTextStream cs(stdout);
cs << formattedMessage << endl;
auto& logger = instance();
// locker mutex scope
{
QMutexLocker locker(&logger.mutex);
logger.queue.enqueue(formattedMessage);
}
if (!logger.writeFuture.isRunning())
{
// 使用QtConcurrent::run在后台线程中异步写入日志文件
logger.writeFuture = QtConcurrent::run(&instance(), &TyLogger::write);
}
}
static TyLogger& instance()
{
// C++11标准保证静态局部变量的初始化是线程安全的
static TyLogger logger;
return logger;
}
private:
void createLogFile()
{
QString logDirPath = "Logs";
QDir logDir(logDirPath);
if (!logDir.exists()) {
logDir.mkpath(".");
}
QString logFilePath = logDirPath + "/" + QDateTime::currentDateTime().toString("yyyy-MM-dd") + ".log";
file.setFileName(logFilePath);
file.open(QIODevice::WriteOnly | QIODevice::Append);
currentLogFileDate = QDate::currentDate();
}
bool isCurrentLogFile() const
{
return currentLogFileDate == QDate::currentDate();
}
private:
QMutex mutex;
QQueue<QString> queue;
//QAtomicInt writeRunning;
QFuture<void> writeFuture;
QFile file;
QDate currentLogFileDate;
};
#endif // TY_LOGGER_HEADER