Krita Source Code Documentation
Loading...
Searching...
No Matches
KisUsageLogger Class Reference

The KisUsageLogger class logs messages to a logfile. More...

#include <KisUsageLogger.h>

Classes

struct  Private
 

Public Member Functions

 KisUsageLogger ()
 
 ~KisUsageLogger ()
 

Static Public Member Functions

static QString basicSystemInfo ()
 
static void close ()
 
static void initialize ()
 
static void log (const QString &message)
 Logs with date/time.
 
static QString screenInformation ()
 Returns information about all available screens.
 
static void writeHeader ()
 
static void writeLocaleSysInfo ()
 
static void writeSysInfo (const QString &message)
 Writes to the system information file and Krita log.
 

Private Member Functions

void rotateLog ()
 

Private Attributes

const QScopedPointer< Privated
 

Static Private Attributes

static const int s_maxLogs {20}
 
static const QString s_sectionHeader
 

Detailed Description

The KisUsageLogger class logs messages to a logfile.

Definition at line 17 of file KisUsageLogger.h.

Constructor & Destructor Documentation

◆ KisUsageLogger()

KisUsageLogger::KisUsageLogger ( )

Definition at line 59 of file KisUsageLogger.cpp.

60 : d(new Private)
61{
62 if (!QFileInfo(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).exists()) {
63 QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
64 }
65 d->logFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/krita.log");
66 d->sysInfoFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/krita-sysinfo.log");
67
68 QFileInfo fi(d->logFile.fileName());
69 if (fi.size() > 100 * 1000 * 1000) { // 100 mb seems a reasonable max
70 if (d->logFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
71 d->logFile.close();
72 } else {
73 qWarning() << "Could not clear the >100MB" << d->logFile.fileName() << ":" << d->logFile.errorString();
74 }
75 }
76 else {
77 rotateLog();
78 }
79
80 if (!d->logFile.open(QFile::Append | QFile::Text)) {
81 qWarning() << "Could not open" << d->logFile.fileName() << "for writing:" << d->logFile.errorString();
82 }
83 if (!d->sysInfoFile.open(QFile::WriteOnly | QFile::Text)) {
84 qWarning() << "Could not open" << d->sysInfoFile.fileName() << "for writing:" << d->sysInfoFile.errorString();
85 }
86}
const QScopedPointer< Private > d

References d, and rotateLog().

◆ ~KisUsageLogger()

KisUsageLogger::~KisUsageLogger ( )

Definition at line 88 of file KisUsageLogger.cpp.

89{
90 if (d->active) {
91 close();
92 }
93}
static void close()

References close(), and d.

Member Function Documentation

◆ basicSystemInfo()

QString KisUsageLogger::basicSystemInfo ( )
static

basic system information (there is other information spread in the code check usages of writeSysInfo for details)

Definition at line 103 of file KisUsageLogger.cpp.

104{
105 QString systemInfo;
106
107 // NOTE: This is intentionally not translated!
108
109 // Krita version info
110 systemInfo.append("Krita\n");
111 systemInfo.append("\n Version: ").append(KritaVersionWrapper::versionString(true));
112#ifdef Q_OS_WIN
113 {
114 using namespace KisWindowsPackageUtils;
115 QString packageFamilyName;
116 QString packageFullName;
117 systemInfo.append("\n Installation type: ");
118 if (tryGetCurrentPackageFamilyName(&packageFamilyName) && tryGetCurrentPackageFullName(&packageFullName)) {
119 systemInfo.append("Store / MSIX package\n Family Name: ")
120 .append(packageFamilyName)
121 .append("\n Full Name: ")
122 .append(packageFullName);
123 } else {
124 systemInfo.append("installer / portable package");
125 }
126 }
127#endif
128#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
129 // Attribute does nothing on Qt6
130 systemInfo.append("\n Hidpi: ").append(QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling) ? "true" : "false");
131#endif
132#ifdef Q_OS_MACOS
133 KisMacosEntitlements entitlements;
134 systemInfo.append("\n Sandbox: ").append((entitlements.sandbox()) ? "true" : "false");
135#endif
136 systemInfo.append("\n\n");
137
138 systemInfo.append("Qt\n");
139 systemInfo.append("\n Version (compiled): ").append(QT_VERSION_STR);
140 systemInfo.append("\n Version (loaded): ").append(qVersion());
141 systemInfo.append("\n\n");
142
143 // OS information
144 systemInfo.append("OS Information\n");
145 systemInfo.append("\n Build ABI: ").append(QSysInfo::buildAbi());
146 systemInfo.append("\n Build CPU: ").append(QSysInfo::buildCpuArchitecture());
147 systemInfo.append("\n CPU: ").append(QSysInfo::currentCpuArchitecture());
148 systemInfo.append("\n Kernel Type: ").append(QSysInfo::kernelType());
149 systemInfo.append("\n Kernel Version: ").append(QSysInfo::kernelVersion());
150 systemInfo.append("\n Pretty Productname: ").append(QSysInfo::prettyProductName());
151 systemInfo.append("\n Product Type: ").append(QSysInfo::productType());
152 systemInfo.append("\n Product Version: ").append(QSysInfo::productVersion());
153
154#ifdef Q_OS_ANDROID
155 QString manufacturer =
156 QAndroidJniObject::getStaticObjectField("android/os/Build", "MANUFACTURER", "Ljava/lang/String;").toString();
157 const QString model =
158 QAndroidJniObject::getStaticObjectField("android/os/Build", "MODEL", "Ljava/lang/String;").toString();
159 manufacturer[0] = manufacturer[0].toUpper();
160 systemInfo.append("\n Product Model: ").append(manufacturer + " " + model);
161#elif defined(Q_OS_LINUX)
162 systemInfo.append("\n Desktop: ").append(qgetenv("XDG_CURRENT_DESKTOP"));
163
164 systemInfo.append("\n Appimage build: ").append(qEnvironmentVariableIsSet("APPIMAGE") ? "Yes" : "No");
165#elif defined(Q_OS_WIN)
166 systemInfo.append("\n Result of IsWindows10OrGreater(): ").append(IsWindows10OrGreater() ? "Yes" : "No");
167#endif
168 systemInfo.append("\n\n");
169
170 return systemInfo;
171}
bool tryGetCurrentPackageFullName(QString *outName)
bool tryGetCurrentPackageFamilyName(QString *outName)
KRITAVERSION_EXPORT QString versionString(bool checkGit=false)

References KisMacosEntitlements::sandbox(), and KritaVersionWrapper::versionString().

◆ close()

void KisUsageLogger::close ( )
static

Definition at line 216 of file KisUsageLogger.cpp.

217{
218 log("CLOSING SESSION");
219 s_instance->d->active = false;
220 s_instance->d->logFile.flush();
221 s_instance->d->logFile.close();
222 s_instance->d->sysInfoFile.flush();
223 s_instance->d->sysInfoFile.close();
224}
static void log(const QString &message)
Logs with date/time.

References log().

◆ initialize()

void KisUsageLogger::initialize ( )
static

Definition at line 95 of file KisUsageLogger.cpp.

96{
97 s_instance->d->active = true;
98
99 QString systemInfo = basicSystemInfo();
100 s_instance->d->sysInfoFile.write(systemInfo.toUtf8());
101}
static QString basicSystemInfo()

References basicSystemInfo().

◆ log()

void KisUsageLogger::log ( const QString & message)
static

Logs with date/time.

Definition at line 226 of file KisUsageLogger.cpp.

227{
228 QMutexLocker locker(&s_instance->d->mutex);
229
230 if (!s_instance->d->active) return;
231 if (!s_instance->d->logFile.isOpen()) return;
232
233 s_instance->d->logFile.write(QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8());
234 s_instance->d->logFile.write(": ");
235 s_instance->d->logFile.write(message.toUtf8());
236 s_instance->d->logFile.write("\n");
237 s_instance->d->logFile.flush();
238}
QString toString(const QString &value)

◆ rotateLog()

void KisUsageLogger::rotateLog ( )
private

Definition at line 316 of file KisUsageLogger.cpp.

317{
318 if (!d->logFile.exists()) { return; }
319
320 // Check for CLOSING SESSION
321 if (d->logFile.open(QFile::ReadOnly)) {
322 QString log = QString::fromUtf8(d->logFile.readAll());
323 if (!log.split(s_sectionHeader).last().contains("CLOSING SESSION")) {
324 log.append("\nKRITA DID NOT CLOSE CORRECTLY\n");
325 QString crashLog = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/kritacrash.log");
326 QFile f(crashLog);
327 if (f.open(QFile::ReadOnly)) {
328 QString crashes = QString::fromUtf8(f.readAll());
329 f.close();
330
331 QStringList crashlist = crashes.split("-------------------");
332 log.append(QString("\nThere were %1 crashes in total in the crash log.\n").arg(crashlist.size()));
333
334 if (crashes.size() > 0) {
335 log.append(crashlist.last());
336 }
337 }
338 d->logFile.close();
339 if (d->logFile.open(QFile::WriteOnly)) {
340 d->logFile.write(log.toUtf8());
341 }
342 }
343 d->logFile.flush();
344 d->logFile.close();
345 }
346
347 // Rotate
348 if (d->logFile.open(QFile::ReadOnly)) {
349 QString log = QString::fromUtf8(d->logFile.readAll());
350 d->logFile.close();
351 QStringList logItems = log.split("SESSION:");
352 QStringList keptItems;
353 int sectionCount = logItems.size();
354 if (sectionCount > s_maxLogs) {
355 for (int i = sectionCount - s_maxLogs; i < sectionCount; ++i) {
356 if (logItems.size() > i ) {
357 keptItems.append(logItems[i]);
358 }
359 }
360
361 if (d->logFile.open(QFile::WriteOnly)) {
362 d->logFile.write(keptItems.join("\nSESSION:").toUtf8());
363 d->logFile.flush();
364 d->logFile.close();
365 }
366 }
367 }
368}
static const int s_maxLogs
static const QString s_sectionHeader

References d, log(), s_maxLogs, and s_sectionHeader.

◆ screenInformation()

QString KisUsageLogger::screenInformation ( )
static

Returns information about all available screens.

Definition at line 281 of file KisUsageLogger.cpp.

282{
283 QList<QScreen*> screens = qApp->screens();
284
285 QString info;
286 info.append("Display Information");
287 info.append("\nNumber of screens: ").append(QString::number(screens.size()));
288
289 for (int i = 0; i < screens.size(); ++i ) {
290 QScreen *screen = screens[i];
291 info.append("\n\tScreen: ").append(QString::number(i));
292 info.append("\n\t\tName: ").append(screen->name());
293 info.append("\n\t\tDepth: ").append(QString::number(screen->depth()));
294 info.append("\n\t\tScale: ").append(QString::number(screen->devicePixelRatio()));
295 info.append("\n\t\tPhysical DPI").append(QString::number(screen->physicalDotsPerInch()));
296 info.append("\n\t\tLogical DPI").append(QString::number(screen->logicalDotsPerInch()));
297 info.append("\n\t\tPhysical Size: ").append(QString::number(screen->physicalSize().width()))
298 .append(", ")
299 .append(QString::number(screen->physicalSize().height()));
300 info.append("\n\t\tPosition: ").append(QString::number(screen->geometry().x()))
301 .append(", ")
302 .append(QString::number(screen->geometry().y()));
303 info.append("\n\t\tResolution in pixels: ").append(QString::number(screen->geometry().width()))
304 .append("x")
305 .append(QString::number(screen->geometry().height()));
306 info.append("\n\t\tManufacturer: ").append(screen->manufacturer());
307 info.append("\n\t\tModel: ").append(screen->model());
308 info.append("\n\t\tRefresh Rate: ").append(QString::number(screen->refreshRate()));
309 info.append("\n\t\tSerial Number: ").append(screen->serialNumber());
310
311 }
312 info.append("\n");
313 return info;
314}

◆ writeHeader()

void KisUsageLogger::writeHeader ( )
static

Definition at line 254 of file KisUsageLogger.cpp.

255{
256 Q_ASSERT(s_instance->d->sysInfoFile.isOpen());
257 s_instance->d->logFile.write(s_sectionHeader.toUtf8());
258
259 QString sessionHeader = QString("SESSION: %1. Executing %2\n\n")
260 .arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))
261 .arg(qApp->arguments().join(' '));
262
263 s_instance->d->logFile.write(sessionHeader.toUtf8());
264
265 QString KritaAndQtVersion;
266 KritaAndQtVersion.append("Krita Version: ").append(KritaVersionWrapper::versionString(true))
267 .append(", Qt version compiled: ").append(QT_VERSION_STR)
268 .append(", loaded: ").append(qVersion())
269 .append(". Process ID: ")
270 .append(QString::number(qApp->applicationPid())).append("\n");
271
272 KritaAndQtVersion.append("-- -- -- -- -- -- -- --\n");
273 s_instance->d->logFile.write(KritaAndQtVersion.toUtf8());
274 s_instance->d->logFile.flush();
275 log(QString("Style: %1. Available styles: %2")
276 .arg(qApp->style()->objectName(),
277 QStyleFactory::keys().join(", ")));
278
279}

References log(), s_sectionHeader, and KritaVersionWrapper::versionString().

◆ writeLocaleSysInfo()

void KisUsageLogger::writeLocaleSysInfo ( )
static

Definition at line 173 of file KisUsageLogger.cpp.

174{
175 if (!s_instance->d->active) {
176 return;
177 }
178 QString systemInfo;
179 systemInfo.append("Locale\n");
180 systemInfo.append("\n Languages: ").append(KLocalizedString::languages().join(", "));
181 systemInfo.append("\n C locale: ").append(std::setlocale(LC_ALL, nullptr));
182 systemInfo.append("\n QLocale current: ").append(QLocale().bcp47Name());
183 systemInfo.append("\n QLocale system: ").append(QLocale::system().bcp47Name());
184 const QTextCodec *codecForLocale = QTextCodec::codecForLocale();
185 systemInfo.append("\n QTextCodec for locale: ").append(codecForLocale->name());
186#ifdef Q_OS_WIN
187 {
188 systemInfo.append("\n Process ACP: ");
189 CPINFOEXW cpInfo {};
190 if (GetCPInfoExW(CP_ACP, 0, &cpInfo)) {
191 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
192 } else {
193 // Shouldn't happen, but just in case
194 systemInfo.append(QString::number(GetACP()));
195 }
196 wchar_t lcData[2];
197 int result = GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, lcData, sizeof(lcData) / sizeof(lcData[0]));
198 if (result == 2) {
199 systemInfo.append("\n System locale default ACP: ");
200 int systemACP = lcData[1] << 16 | lcData[0];
201 if (systemACP == CP_ACP) {
202 systemInfo.append("N/A");
203 } else if (GetCPInfoExW(systemACP, 0, &cpInfo)) {
204 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
205 } else {
206 // Shouldn't happen, but just in case
207 systemInfo.append(QString::number(systemACP));
208 }
209 }
210 }
211#endif
212 systemInfo.append("\n\n");
213 s_instance->d->sysInfoFile.write(systemInfo.toUtf8());
214}

◆ writeSysInfo()

void KisUsageLogger::writeSysInfo ( const QString & message)
static

Writes to the system information file and Krita log.

Definition at line 240 of file KisUsageLogger.cpp.

241{
242 QMutexLocker locker(&s_instance->d->mutex);
243
244 if (!s_instance->d->active) return;
245 if (!s_instance->d->sysInfoFile.isOpen()) return;
246
247 s_instance->d->sysInfoFile.write(message.toUtf8());
248 s_instance->d->sysInfoFile.write("\n");
249
250 s_instance->d->sysInfoFile.flush();
251
252}

Member Data Documentation

◆ d

const QScopedPointer<Private> KisUsageLogger::d
private

Definition at line 53 of file KisUsageLogger.h.

◆ s_maxLogs

const int KisUsageLogger::s_maxLogs {20}
staticprivate

Definition at line 56 of file KisUsageLogger.h.

56{20};

◆ s_sectionHeader

const QString KisUsageLogger::s_sectionHeader
staticprivate

Definition at line 55 of file KisUsageLogger.h.


The documentation for this class was generated from the following files: