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 60 of file KisUsageLogger.cpp.

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

References d, and rotateLog().

◆ ~KisUsageLogger()

KisUsageLogger::~KisUsageLogger ( )

Definition at line 89 of file KisUsageLogger.cpp.

90{
91 if (d->active) {
92 close();
93 }
94}
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 104 of file KisUsageLogger.cpp.

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

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

References log().

◆ initialize()

void KisUsageLogger::initialize ( )
static

Definition at line 96 of file KisUsageLogger.cpp.

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

References basicSystemInfo().

◆ log()

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

Logs with date/time.

Definition at line 227 of file KisUsageLogger.cpp.

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

◆ rotateLog()

void KisUsageLogger::rotateLog ( )
private

Definition at line 323 of file KisUsageLogger.cpp.

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

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

◆ writeHeader()

void KisUsageLogger::writeHeader ( )
static

Definition at line 255 of file KisUsageLogger.cpp.

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

References KisAndroidExitInfo::buildLogString(), KisAndroidExitInfo::getLast(), KisAndroidExitInfo::isValid(), log(), s_sectionHeader, and KritaVersionWrapper::versionString().

◆ writeLocaleSysInfo()

void KisUsageLogger::writeLocaleSysInfo ( )
static

Definition at line 174 of file KisUsageLogger.cpp.

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

◆ writeSysInfo()

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

Writes to the system information file and Krita log.

Definition at line 241 of file KisUsageLogger.cpp.

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

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: