QtCanpool 3.3.0
载入中...
搜索中...
未找到
qxlogger.cpp
浏览该文件的文档.
1
6#include "qxlogger.h"
7
8#include <QtCore/QDateTime>
9#include <QtCore/QDir>
10#include <QtCore/QFile>
11#include <QtCore/QFileInfo>
12#include <QtCore/QMutex>
13#include <QtCore/QMutexLocker>
14#include <QtCore/qlogging.h>
15
16#include <cstdio>
17
19
20namespace
21{
22
23struct LoggerState {
24 QxLogger::Options options;
25 QFile file;
26 QMutex mutex;
27 bool enabled;
28 QtMessageHandler previous;
29
30 LoggerState()
31 : enabled(false)
32 , previous(nullptr)
33 {
34 }
35};
36
42LoggerState &state()
43{
44 static LoggerState s;
45 return s;
46}
47
48QxLogger::Level levelFromQt(QtMsgType type)
49{
50 switch (type) {
51 case QtDebugMsg:
52 return QxLogger::Debug;
53 case QtInfoMsg:
54 return QxLogger::Info;
55 case QtWarningMsg:
56 return QxLogger::Warning;
57 case QtCriticalMsg:
58 return QxLogger::Critical;
59 case QtFatalMsg:
60 break;
61 }
62 return QxLogger::Fatal;
63}
64
65char levelLetter(QxLogger::Level level)
66{
67 switch (level) {
68 case QxLogger::Debug:
69 return 'D';
70 case QxLogger::Info:
71 return 'I';
72 case QxLogger::Warning:
73 return 'W';
74 case QxLogger::Critical:
75 return 'C';
76 case QxLogger::Fatal:
77 break;
78 }
79 return 'F';
80}
81
82QString backupName(const QString &fileName, int index)
83{
84 return fileName + QLatin1Char('.') + QString::number(index);
85}
86
92void rotate(LoggerState &s, qint64 pending)
93{
94 if (s.options.maxFileSize <= 0 || s.options.maxBackups <= 0) {
95 return;
96 }
97 if (s.file.size() + pending <= s.options.maxFileSize) {
98 return;
99 }
100
101 const QString base = s.options.fileName;
102 s.file.close();
103
104 for (int i = s.options.maxBackups; i > 1; --i) {
105 const QString to = backupName(base, i);
106 QFile::remove(to);
107 QFile::rename(backupName(base, i - 1), to);
108 }
109 QFile::remove(backupName(base, 1));
110 QFile::rename(base, backupName(base, 1));
111
112 s.file.setFileName(base);
113 s.file.open(QIODevice::WriteOnly | QIODevice::Append);
114}
115
116void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
117{
118 QxLogger::write(levelFromQt(type), QString::fromLatin1(context.category ? context.category : "default"), message);
119}
120
121} // namespace
122
123bool QxLogger::init(const Options &options)
124{
125 LoggerState &s = state();
126 QMutexLocker locker(&s.mutex);
127
128 if (!s.enabled) {
129 s.previous = qInstallMessageHandler(messageHandler);
130 s.enabled = true;
131 }
132 s.options = options;
133
134 if (s.file.isOpen()) {
135 s.file.close();
136 }
137 if (options.fileName.isEmpty()) {
138 s.file.setFileName(QString());
139 return true;
140 }
141
142 QDir().mkpath(QFileInfo(options.fileName).absolutePath());
143 s.file.setFileName(options.fileName);
144 return s.file.open(QIODevice::WriteOnly | QIODevice::Append);
145}
146
147void QxLogger::shutdown()
148{
149 LoggerState &s = state();
150 QMutexLocker locker(&s.mutex);
151
152 if (!s.enabled) {
153 return;
154 }
155 if (s.file.isOpen()) {
156 s.file.flush();
157 s.file.close();
158 }
159 qInstallMessageHandler(s.previous);
160 s.previous = nullptr;
161 s.enabled = false;
162 s.options = Options();
163}
164
165bool QxLogger::isEnabled()
166{
167 LoggerState &s = state();
168 QMutexLocker locker(&s.mutex);
169 return s.enabled;
170}
171
172QString QxLogger::fileName()
173{
174 LoggerState &s = state();
175 QMutexLocker locker(&s.mutex);
176 return s.file.isOpen() ? s.file.fileName() : QString();
177}
178
179void QxLogger::flush()
180{
181 LoggerState &s = state();
182 QMutexLocker locker(&s.mutex);
183 if (s.file.isOpen()) {
184 s.file.flush();
185 }
186}
187
188void QxLogger::write(Level level, const QLoggingCategory &category, const QString &message)
189{
190 write(level, QString::fromLatin1(category.categoryName()), message);
191}
192
193void QxLogger::write(Level level, const QString &category, const QString &message)
194{
195 LoggerState &s = state();
196 QMutexLocker locker(&s.mutex);
197
198 if (!s.enabled || level < s.options.level) {
199 return;
200 }
201
202 const QString line = QStringLiteral("%1 [%2] %3: %4\n")
203 .arg(QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz")))
204 .arg(QLatin1Char(levelLetter(level)))
205 .arg(category)
206 .arg(message);
207
208 if (s.options.toConsole) {
209 const QByteArray utf8 = line.toUtf8();
210 std::fwrite(utf8.constData(), 1, static_cast<size_t>(utf8.size()), stderr);
211 std::fflush(stderr);
212 }
213
214 if (s.file.isOpen()) {
215 const QByteArray utf8 = line.toUtf8();
216 rotate(s, utf8.size());
217 s.file.write(utf8);
218 s.file.flush();
219 }
220}
221
Level
Level letters used in the output, in ascending severity.
Definition qxlogger.h:29
#define QX_CORE_BEGIN_NAMESPACE
#define QX_CORE_END_NAMESPACE
QFile file
Definition qxlogger.cpp:25
bool enabled
Definition qxlogger.cpp:27
QtMessageHandler previous
Definition qxlogger.cpp:28
QxLogger::Options options
Definition qxlogger.cpp:24
QMutex mutex
Definition qxlogger.cpp:26
const char * fileName
Definition qxtheme.cpp:26
QColor base