[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