Akonadi

akdebug.cpp
1 /*
2  SPDX-FileCopyrightText: 2008 Volker Krause <[email protected]>
3 
4  Inspired by kdelibs/kdecore/io/kdebug.h
5  SPDX-FileCopyrightText: 1997 Matthias Kalle Dalheimer <[email protected]>
6  SPDX-FileCopyrightText: 2002 Holger Freyther <[email protected]>
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 <QDir>
16 #include <QFile>
17 #include <QFileInfo>
18 #include <QMutex>
19 #include <QLoggingCategory>
20 #include <QDateTime>
21 
22 #include <KCrash/KCrash>
23 
24 #include <cassert>
25 
26 class FileDebugStream : public QIODevice
27 {
28  Q_OBJECT
29 public:
30  FileDebugStream()
31  : mType(QtCriticalMsg)
32  {
33  open(WriteOnly);
34  }
35 
36  bool isSequential() const override
37  {
38  return true;
39  }
40  qint64 readData(char * /*data*/, qint64 /*maxlen*/) override {
41  return 0;
42  }
43  qint64 readLineData(char * /*data*/, qint64 /*maxlen*/) override {
44  return 0;
45  }
46 
47  qint64 writeData(const char *data, qint64 len) override {
48  if (!mFileName.isEmpty())
49  {
50  QFile outputFile(mFileName);
52  outputFile.write(data, len);
53  outputFile.putChar('\n');
54  outputFile.close();
55  }
56 
57  return len;
58  }
59 
60  void setFileName(const QString &fileName)
61  {
62  mFileName = fileName;
63  }
64 
65  void setType(QtMsgType type)
66  {
67  mType = type;
68  }
69 private:
70  QString mFileName;
71  QtMsgType mType;
72 };
73 
74 class DebugPrivate
75 {
76 public:
77  DebugPrivate()
78  : origHandler(nullptr)
79  {
80  }
81 
82  ~DebugPrivate()
83  {
84  qInstallMessageHandler(origHandler);
85  file.close();
86  }
87 
88  static QString errorLogFileName(const QString &name)
89  {
90  return Akonadi::StandardDirs::saveDir("data")
91  + QDir::separator()
92  + name
93  + QLatin1String(".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 
179 Q_GLOBAL_STATIC(DebugPrivate, sInstance) // NOLINT(readability-redundant-member-init)
180 
181 void 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 
196 void akCategoryFilter(QLoggingCategory *category)
197 {
198  if ((qstrcmp(category->categoryName(), sInstance()->loggingCategory) == 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 
210 void akInit(const QString &appName)
211 {
213 
214  const QString name = QFileInfo(appName).fileName();
215  const auto errorLogFile = DebugPrivate::errorLogFileName(name);
216  QFileInfo infoOld(errorLogFile + QLatin1String(".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",
222  qUtf8Printable(fileOld.fileName()),
223  qUtf8Printable(fileOld.errorString()));
224  }
225  }
226 
227  QFileInfo info(errorLogFile);
228  if (info.exists()) {
229  QFile file(info.absoluteFilePath());
230  const QString oldName = errorLogFile + QLatin1String(".old");
231  const bool success = file.copy(oldName);
232  if (!success) {
233  qFatal("Cannot rename log file '%s' to '%s': %s",
234  qUtf8Printable(file.fileName()),
235  qUtf8Printable(oldName),
236  qUtf8Printable(file.errorString()));
237  }
238  }
239 
240  QtMessageHandler origHandler = qInstallMessageHandler(akMessageHandler);
241  sInstance()->setName(name);
242  sInstance()->setOrigHandler(origHandler);
243 }
244 
245 void akMakeVerbose(const QByteArray &category)
246 {
247  sInstance()->loggingCategory = category;
249  sInstance()->setOrigCategoryFilter(oldFilter);
250 }
251 
252 #include "akdebug.moc"
253 
QString toString(Qt::DateFormat format) const const
void setEnabled(QtMsgType type, bool enable)
QString name(const QVariant &location)
bool remove()
KCRASH_EXPORT void initialize()
QLoggingCategory::CategoryFilter installFilter(QLoggingCategory::CategoryFilter filter)
virtual bool open(QIODevice::OpenMode mode)
virtual qint64 readData(char *data, qint64 maxSize)=0
QChar separator()
virtual bool isSequential() const const
Q_OBJECTQ_OBJECT
QString fileName() const const
typedef CategoryFilter
const char * constData() const const
const char * categoryName() const const
virtual qint64 readLineData(char *data, qint64 maxSize)
QDateTime currentDateTime()
virtual qint64 writeData(const char *data, qint64 maxSize)=0
int size() const const
bool mkpath(const QString &dirPath) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun Jul 12 2020 23:16:55 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.