Akonadi

akdebug.cpp
1/*
2 SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org>
3
4 Inspired by kdelibs/kdecore/io/kdebug.h
5 SPDX-FileCopyrightText: 1997 Matthias Kalle Dalheimer <kalle@kde.org>
6 SPDX-FileCopyrightText: 2002 Holger Freyther <freyther@kde.org>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#include "akdebug.h"
12
13#include "private/standarddirs_p.h"
14
15#include <QDateTime>
16#include <QDir>
17#include <QFile>
18#include <QFileInfo>
19#include <QLoggingCategory>
20#include <QMutex>
21
22#include <KCrash>
23
24#include <cassert>
25
26class FileDebugStream : public QIODevice
27{
29public:
30 FileDebugStream()
31 : mType(QtCriticalMsg)
32 {
34 }
35
36 bool isSequential() const override
37 {
38 return true;
39 }
40 qint64 readData(char * /*data*/, qint64 /*maxlen*/) override
41 {
42 return 0;
43 }
44 qint64 readLineData(char * /*data*/, qint64 /*maxlen*/) override
45 {
46 return 0;
47 }
48
49 qint64 writeData(const char *data, qint64 len) override
50 {
51 if (!mFileName.isEmpty()) {
52 QFile outputFile(mFileName);
54 outputFile.write(data, len);
55 outputFile.putChar('\n');
56 outputFile.close();
57 }
58
59 return len;
60 }
61
62 void setFileName(const QString &fileName)
63 {
64 mFileName = fileName;
65 }
66
67 void setType(QtMsgType type)
68 {
69 mType = type;
70 }
71
72private:
73 QString mFileName;
74 QtMsgType mType;
75};
76
77class DebugPrivate
78{
79public:
80 DebugPrivate()
81 : origHandler(nullptr)
82 {
83 }
84
85 ~DebugPrivate()
86 {
87 qInstallMessageHandler(origHandler);
88 file.close();
89 }
90
91 static QString errorLogFileName(const QString &name)
92 {
93 return Akonadi::StandardDirs::saveDir("data") + QDir::separator() + name + QLatin1StringView(".error");
94 }
95
96 QString errorLogFileName() const
97 {
98 return errorLogFileName(name);
99 }
100
101 void log(QtMsgType type, const QMessageLogContext &context, const QString &msg)
102 {
103 QMutexLocker locker(&mutex);
104#ifdef QT_NO_DEBUG_OUTPUT
105 if (type == QtDebugMsg) {
106 return;
107 }
108#endif
109 QByteArray buf;
110 QTextStream str(&buf);
112 switch (type) {
113 case QtDebugMsg:
114 str << "DEBUG";
115 break;
116 case QtInfoMsg:
117 str << "INFO ";
118 break;
119 case QtWarningMsg:
120 str << "WARN ";
121 break;
122 case QtFatalMsg:
123 str << "FATAL";
124 break;
125 case QtCriticalMsg:
126 str << "CRITICAL";
127 break;
128 }
129 str << "] " << context.category << ": ";
130 if (context.file && *context.file && context.line) {
131 str << context.file << ":" << context.line << ": ";
132 }
133 if (context.function && *context.function) {
134 str << context.function << ": ";
135 }
136 str << msg << "\n";
137 str.flush();
138 file.write(buf.constData(), buf.size());
139 file.flush();
140
141 if (origHandler) {
142 origHandler(type, context, msg);
143 }
144 }
145
146 void setName(const QString &appName)
147 {
148 name = appName;
149
150 if (file.isOpen()) {
151 file.close();
152 }
153 QFileInfo finfo(errorLogFileName());
154 if (!finfo.absoluteDir().exists()) {
155 QDir().mkpath(finfo.absolutePath());
156 }
157 file.setFileName(errorLogFileName());
159 }
160
161 void setOrigHandler(QtMessageHandler origHandler_)
162 {
163 origHandler = origHandler_;
164 }
165
166 void setOrigCategoryFilter(QLoggingCategory::CategoryFilter origFilter_)
167 {
168 origFilter = origFilter_;
169 }
170
171 QMutex mutex;
172 QFile file;
173 QString name;
174 QtMessageHandler origHandler;
176 QByteArray loggingCategory;
177};
178
179Q_GLOBAL_STATIC(DebugPrivate, sInstance) // NOLINT(readability-redundant-member-init)
180
181void akMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
182{
183 switch (type) {
184 case QtDebugMsg:
185 case QtInfoMsg:
186 case QtWarningMsg:
187 case QtCriticalMsg:
188 sInstance()->log(type, context, msg);
189 break;
190 case QtFatalMsg:
191 sInstance()->log(QtInfoMsg, context, msg);
192 abort();
193 }
194}
195
196void akCategoryFilter(QLoggingCategory *category)
197{
198 if ((qstrcmp(category->categoryName(), sInstance()->loggingCategory.constData()) == 0)
199 || (qstrcmp(category->categoryName(), "org.kde.pim.akonadiprivate") == 0)) {
200 category->setEnabled(QtDebugMsg, true);
201 category->setEnabled(QtInfoMsg, true);
202 category->setEnabled(QtWarningMsg, true);
203 category->setEnabled(QtCriticalMsg, true);
204 category->setEnabled(QtFatalMsg, true);
205 } else if (sInstance()->origFilter) {
206 sInstance()->origFilter(category);
207 }
208}
209
210void akInit(const QString &appName)
211{
213
214 const QString name = QFileInfo(appName).fileName();
215 const auto errorLogFile = DebugPrivate::errorLogFileName(name);
216 QFileInfo infoOld(errorLogFile + QLatin1StringView(".old"));
217 if (infoOld.exists()) {
218 QFile fileOld(infoOld.absoluteFilePath());
219 const bool success = fileOld.remove();
220 if (!success) {
221 qFatal("Cannot remove old log file '%s': %s", qUtf8Printable(fileOld.fileName()), qUtf8Printable(fileOld.errorString()));
222 }
223 }
224
225 QFileInfo info(errorLogFile);
226 if (info.exists()) {
227 QFile file(info.absoluteFilePath());
228 const QString oldName = errorLogFile + QLatin1StringView(".old");
229 const bool success = file.copy(oldName);
230 if (!success) {
231 qFatal("Cannot rename log file '%s' to '%s': %s", qUtf8Printable(file.fileName()), qUtf8Printable(oldName), qUtf8Printable(file.errorString()));
232 }
233 }
234
235 QtMessageHandler origHandler = qInstallMessageHandler(akMessageHandler);
236 sInstance()->setName(name);
237 sInstance()->setOrigHandler(origHandler);
238}
239
240void akMakeVerbose(const QByteArray &category)
241{
242 sInstance()->loggingCategory = category;
244 sInstance()->setOrigCategoryFilter(oldFilter);
245}
246
247#include "akdebug.moc"
Q_SCRIPTABLE Q_NOREPLY void abort()
KCRASH_EXPORT void initialize()
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
Category category(StandardShortcut id)
QString name(StandardShortcut id)
QCA_EXPORT QString appName()
const char * constData() const const
qsizetype size() const const
QDateTime currentDateTime()
QString toString(QStringView format, QCalendar cal) const const
bool mkpath(const QString &dirPath) const const
QChar separator()
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
void setFileName(const QString &name)
virtual void close() override
bool flush()
QString fileName() const const
bool isOpen() const const
virtual bool open(QIODeviceBase::OpenMode mode)
qint64 write(const QByteArray &data)
typedef CategoryFilter
CategoryFilter installFilter(CategoryFilter filter)
Q_OBJECTQ_OBJECT
T qobject_cast(QObject *object)
bool isEmpty() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:38 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.