[Development] Cake and eating it too for qDebug printing to system log - https://codereview.qt-project.org/89357
Thiago Macieira
thiago.macieira at intel.com
Wed Jul 9 23:43:36 CEST 2014
== Problematic ==
Qt 5.3 and dev are currently able to send the output of qDebug, qWarning and
the rest of the logging framework to somewhere other than stderr. That's done
on Windows, BlackBerry, Android, and on Linux systems with journald.
Additionally, there's a pending patch for OS X to use the Apple System Log [5]
and I had a patch for MeeGo that made it go to the standard Unix syslog.
We have a problem of wanting a cake and eating it too:
1) we want applications to send their logging to the system log where
possible, which usually logs more information like the log level, time,
application name and PID. Such a system is searchable and may allow us to add
additional information, like the category (for category logging), file name,
line number, function context, etc.
2) we also want to see the output when we run applications from the terminal
or capture the output with QProcess.
The absence of output causes bug reports like [2] and [4].
== Solutions ==
=== Log to both ===
Aside from the extra overhead, this causes systems that capture both stderr
and the system log to record and display the same message twice. That's the
source of task [3].
This is not an option.
=== Log to stderr only ===
That results in loss of information, since the system logs are richer and more
searchable.
What's more, on Windows that would result in no output at all for GUI
applications. I can't find a lot of information on whether GUI applications
launched from an open command prompt would show anything. IIRC, they don't.
This is not an option.
=== Log to system logs only ===
This causes reports like [4]. But note that the bug is actually in Creator,
for failing to read the log store and display the data, like it does on
Windows with the debug output.
This is an option.
=== Heuristically determine at runtime where to send the log ===
Which is what I'm trying to do above.
On Windows, we check whether we have a console and whether stderr is not NUL.
On Unix, I have implemented the same checks.
We can also use the fact of whether the main application is in debug mode or
not.
== Summary of systems ==
- default stderr: what is stderr connected to when launched from the GUI menu
- system logging: if there's an API and whether non-privileged users can read
from the log
- is stderr useful: whether there are conditions under which writing to
stderr is useful
Android:
- default stderr: /dev/null
- system logging: available
- is stderr useful: barely, it requires a rooted device
BlackBerry:
- default stderr: /dev/null
- system logging: available
- is stderr useful: I don't know, it's possible d5a4732c applies to non-BB
QNX only
OS X and iOS:
- default stderr: captured into system log
- system logging: available
- is stderr useful: yes on OS X, running applications from the terminal
SailfishOS:
- default stderr: captured into the wrong system log
- system logging: available
- is stderr useful: yes, for remote debugging applications
Current Linux desktops with journald:
- default stderr: captured into ~/.xsession-errors
- system logging available: available
- is stderr useful: yes, for launching from terminal
[when Linux desktops start using user-mode systemd, it will be as below]
System services on Linux with journald:
- default stderr: captured into system log
- system logging: available
- is stderr useful: yes, for launching from terminal
Unix without journald:
- default stderr: irrelevant
- system logging: not available (non-root users may not be able to read it)
- is stderr useful: yes, mandatory
Windows GUI apps:
- default stderr: NUL
- system logging: available
- is stderr useful: yes
Windows console apps:
- default stderr: console
- system logging: available
- is stderr useful: yes
== History ==
In the dawn of time, qDebug printed to stderr.
But then came Windows with GUI applications that don't have a console and
stderr is NUL. So Qt applications that did not use CONFIG += console would use
OutputDebugString, which we'd detect by the use or not of Qt's WinMain
function. That was the first "system log" API.
During Qt 5.0 development, we added logging to BlackBerry's slog2. That was
unconditional: all applications, all output.
Similarly for the Android port: when it was introduced, it unconditionally
logged to the the Android log. But in Qt 5.1, there was a commit (289120f8)
that added an environment variable allowing logging to stderr.
During 5.2 development, we stopped using WinMain and instead tried to detect
whether the application has a console window or not. The first two patch sets
of 7fb3906 [1] only checked for the console, but PS3 added a check for whether
stderr was valid even if no console window was present.
For 5.3, we added support for journald on Linux, mostly intended for
SailfishOS. Support was like on Android at the time: an environment variable
was needed to write to stderr; otherwise, it went to journald.
For 5.3.1, support for the environment variable was added to BlackBerry's
slog2 too, matching Android and journald-enabled Linux.
And then some desktop Linux distributions decided to enable journald. The
effect of that is task [6]: Qt Creator shows no output because it goes to
journald.
== References ==
[1] https://codereview.qt-project.org/64599 - merged as 7fb3906 for 5.2
[2] https://bugreports.qt-project.org/browse/QTBUG-32044 - task for [1]
[3] https://bugreports.qt-project.org/browse/QTBUG-34630
[4] https://bugreports.qt-project.org/browse/QTCREATORBUG-12564
[5] https://codereview.qt-project.org/82922 - open for dev
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
More information about the Development
mailing list