mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-05 20:39:59 -08:00
[Doxygen] Logging (#6399)
* [Doxygen] Logging Took 50 minutes Took 36 seconds * [Doxygen] Newline. Took 2 minutes * [Doxygen] Add another example. Took 7 minutes * [Doxygen] \note and \warning Took 4 minutes Took 32 seconds --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
[Rules]
|
||||
# The default log level is info
|
||||
*.debug = false
|
||||
#*.info = true
|
||||
#*.warning = true
|
||||
#*.critical = true
|
||||
#*.fatal = true
|
||||
|
||||
# Uncomment a rule to see debug level logs for that category,
|
||||
# or set <category> = false to disable logging
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@page developer_reference Developer Reference
|
||||
|
||||
- @subpage logging
|
||||
|
||||
- @subpage primer_cards
|
||||
|
||||
- @subpage card_database_schema_and_parsing
|
||||
|
||||
184
doc/doxygen/extra-pages/developer_documentation/logging.md
Normal file
184
doc/doxygen/extra-pages/developer_documentation/logging.md
Normal file
@@ -0,0 +1,184 @@
|
||||
@page logging Logging
|
||||
|
||||
Cockatrice uses QtLogging from the QtCore module for its logging. See
|
||||
the [official documentation](https://doc.qt.io/qt-6/qtlogging.html) for further details.
|
||||
|
||||
# Log Message Pattern
|
||||
|
||||
Any message logged through the QtLogging system automatically conforms to this message pattern:
|
||||
|
||||
Generic:
|
||||
|
||||
```
|
||||
[<timestamp> <log_level>] [<class:function>] - <message> [<filename>:<line_no>]
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
[2025-12-05 14:48:25.908 I] [MainWindow::startupConfigCheck] - Startup: found config with current version [window_main.cpp:951]
|
||||
```
|
||||
|
||||
For more information, see [Logging Setup](#logging-setup).
|
||||
|
||||
# Log Level and Categories
|
||||
|
||||
\note The default log level for the application is info.
|
||||
|
||||
This means that you should only use qInfo() in production-level code if you are truly sure that this message is
|
||||
beneficial to end-users and other developers. As a general rule, if your functionality logs to info more than twice in
|
||||
response to a user interaction, you are advised to consider moving some of these logs down to the debug level.
|
||||
|
||||
\warning You are strongly advised to avoid the use of the generic logging macros (e.g. qDebug(), qInfo(), qWarn()).
|
||||
|
||||
\note You should instead use the corresponding category logging macros (qCDebug(), qCInfo(), qCWarn()) and define
|
||||
logging
|
||||
categories for your log statements.
|
||||
|
||||
Example:
|
||||
|
||||
```c++
|
||||
in .h
|
||||
|
||||
inline Q_LOGGING_CATEGORY(ExampleCategory, "cockatrice_example_category");
|
||||
inline Q_LOGGING_CATEGORY(ExampleSubCategory, "cockatrice_example_category.sub_category");
|
||||
|
||||
in .cpp
|
||||
|
||||
qCInfo(ExampleCategory) << "Info level logs are usually sent through the main category"
|
||||
qCDebug(ExampleSubCategory) << "Debug level logs are permitted their own category to allow selective silencing"
|
||||
```
|
||||
|
||||
For more information on how to enable or disable logging categories,
|
||||
see [Logging Configuration](#logging-configuration).
|
||||
|
||||
# Logging Configuration
|
||||
|
||||
For configuring our logging, we use the qtlogging.ini, located under cockatrice/resources/config/qtlogging.ini, which is
|
||||
baked into the application in release version and set as the QT_LOGGING_CONF environment variable in main.cpp.
|
||||
|
||||
```c++
|
||||
#ifdef Q_OS_APPLE
|
||||
// <build>/cockatrice/cockatrice.app/Contents/MacOS/cockatrice
|
||||
const QByteArray configPath = "../../../qtlogging.ini";
|
||||
#elif defined(Q_OS_UNIX)
|
||||
// <build>/cockatrice/cockatrice
|
||||
const QByteArray configPath = "./qtlogging.ini";
|
||||
#elif defined(Q_OS_WIN)
|
||||
// <build>/cockatrice/Debug/cockatrice.exe
|
||||
const QByteArray configPath = "../qtlogging.ini";
|
||||
#else
|
||||
const QByteArray configPath = "";
|
||||
#endif
|
||||
|
||||
if (!qEnvironmentVariableIsSet(("QT_LOGGING_CONF"))) {
|
||||
// Set the QT_LOGGING_CONF environment variable
|
||||
qputenv("QT_LOGGING_CONF", configPath);
|
||||
}
|
||||
```
|
||||
|
||||
For more information on how to use this file and on how Qt evaluates which logging rules/file to use, please
|
||||
see the [official Qt documentation](https://doc.qt.io/qt-6/qloggingcategory.html#configuring-categories).
|
||||
|
||||
Some examples:
|
||||
|
||||
```
|
||||
# Turn off all logging except everything from card_picture_loader and all sub categories
|
||||
|
||||
[Rules]
|
||||
# The default log level is info
|
||||
*.debug = false
|
||||
*.info = false
|
||||
*.warning = false
|
||||
*.critical = false
|
||||
*.fatal = false
|
||||
|
||||
card_picture_loader.* = true
|
||||
```
|
||||
|
||||
```
|
||||
# Turn off all logging except info level logs from card_picture_loader and all sub categories
|
||||
|
||||
[Rules]
|
||||
# The default log level is info
|
||||
*.debug = false
|
||||
*.info = false
|
||||
*.warning = false
|
||||
*.critical = false
|
||||
*.fatal = false
|
||||
|
||||
card_picture_loader.*.info = true
|
||||
```
|
||||
|
||||
```
|
||||
[Rules]
|
||||
# Turn on debug level logs for card_picture_loader but keep logging for sub categories suppressed
|
||||
*.debug = false
|
||||
|
||||
card_picture_loader.debug = true
|
||||
```
|
||||
|
||||
```
|
||||
[Rules]
|
||||
# Turn on all logs for worker subcategory of card_picture_loader
|
||||
*.debug = false
|
||||
|
||||
card_picture_loader.worker = true
|
||||
```
|
||||
|
||||
```
|
||||
[Rules]
|
||||
# Turn off some noisy and irrelevant startup logging for local development
|
||||
*.debug = false
|
||||
|
||||
qt_translator = false
|
||||
window_main.* = false
|
||||
release_channel = false
|
||||
spoiler_background_updater = false
|
||||
theme_manager = false
|
||||
sound_engine = false
|
||||
tapped_out_interface = false
|
||||
card_database = false
|
||||
card_database.loading = false
|
||||
card_database.loading.success_or_failure = true
|
||||
cockatrice_xml.* = false
|
||||
```
|
||||
|
||||
# Logging Setup
|
||||
|
||||
This is achieved through our logging setup in @ref main.cpp, where we set the message pattern and install a custom
|
||||
logger which replaces the full file path at the end with just the file name (Qt shows the full and quite lengthy path by
|
||||
default).
|
||||
|
||||
```c++
|
||||
qSetMessagePattern(
|
||||
"\033[0m[%{time yyyy-MM-dd h:mm:ss.zzz} "
|
||||
"%{if-debug}\033[36mD%{endif}%{if-info}\033[32mI%{endif}%{if-warning}\033[33mW%{endif}%{if-critical}\033[31mC%{"
|
||||
"endif}%{if-fatal}\033[1;31mF%{endif}\033[0m] [%{function}] - %{message} [%{file}:%{line}]");
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QObject::connect(&app, &QApplication::lastWindowClosed, &app, &QApplication::quit);
|
||||
|
||||
qInstallMessageHandler(CockatriceLogger);
|
||||
```
|
||||
|
||||
```c++
|
||||
static void CockatriceLogger(QtMsgType type, const QMessageLogContext &ctx, const QString &message)
|
||||
{
|
||||
QString logMessage = qFormatLogMessage(type, ctx, message);
|
||||
|
||||
// Regular expression to match the full path in the square brackets and extract only the filename and line number
|
||||
QRegularExpression regex(R"(\[(?:.:)?[\/\\].*[\/\\]([^\/\\]+\:\d+)\])");
|
||||
QRegularExpressionMatch match = regex.match(logMessage);
|
||||
|
||||
if (match.hasMatch()) {
|
||||
// Extract the filename and line number (e.g., "main.cpp:211")
|
||||
QString filenameLine = match.captured(1);
|
||||
|
||||
// Replace the full path in square brackets with just the filename and line number
|
||||
logMessage.replace(match.captured(0), QString("[%1]").arg(filenameLine));
|
||||
}
|
||||
|
||||
Logger::getInstance().log(type, ctx, logMessage);
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user