Benutzerfreundliche Fehlermeldungen

Der erste Schritt bei Fehlern ist meist der Versuch, anhand von Logmeldungen nachzuvollziehen, was die Anwendung zuletzt gemacht hat, bevor das Problem aufgetreten ist. Hier zeigt sich dann schnell, wie gut die Anwendung darauf vorbereitet ist, dem Benutzer bei der Fehlersuche zu helfen. Dazu einige Beispiel:

[2014-05-28 09:47:04 +0200] <Q #0x7f5a08c68780 W #0x7f5a08c688c0> critical/remote: Cannot connect to host 'voip.beutner.name' on port '5665'

Auf den ersten Blick sieht es so aus, als würde die Verbindung nicht aufgebaut werden können. Aber es fehlen einige wichtige Informationen, um die Logmeldung in den Kontext einordnen zu können:

  • Wer hat aus welchem Grund versucht die Verbindung aufzubauen bzw. was für eine Art Verbindung ist es? (Datenbank? Cluster? Was ganz anderes?)
  • Warum ist der Verbindungsaufbau gescheitert (“Connection refused” in diesem Fall, wenn man mit strace nachschaut, warum der connect()-Aufruf fehlschlägt)?
  • Welche Auswirkungen hat dies (in diesem Fall wird der Verbindungsaufbau periodisch erneut versucht, wodurch sich auch die Frage stellt, ob der Fehler wirklich “critical” ist)?

Die andere Seite des Spektrums bietet eine wahre Informationsüberflutung und ist mindestens genauso schlecht:

Caught unhandled exception.
Current time: 2014-05-28 09:46:51 +0200
***
* Application version: v2.0.0-beta1-8-g641ff1f
* Installation root: /home/gbeutner/i2
* Sysconf directory: /home/gbeutner/i2/etc
* Local state directory: /home/gbeutner/i2/var
* Package data directory: /home/gbeutner/i2/share/icinga2
* State path: /home/gbeutner/i2/var/lib/icinga2/icinga2.state
* PID path: /home/gbeutner/i2/var/run/icinga2/icinga2.pid
* Application type: icinga/IcingaApplication
***
/home/gbeutner/icinga2/lib/base/application.cpp(671): Throw in function void icinga::Application::UpdatePidFile(const icinga::String &, pid_t)
Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error> >
std::exception::what: Could not open PID file '/home/gbeutner/i2/var/run/icinga2/icinga2.pid'
[icinga::StackTrace*] =
(0) libbase.so: void boost::throw_exception<boost::exception_detail::error_info_injector<std::runtime_error> >(boost::exception_detail::error_info_injector<std::runtime_error> const&) (+0xb3) [0x7fec91f6b323] (throw_exception.hpp:61)
(1) libbase.so: void boost::exception_detail::throw_exception_<std::runtime_error>(std::runtime_error const&, char const*, char const*, int) (+0x66) [0x7fec91f64c96] (exception.hpp:276)
(2) libbase.so: icinga::Application::UpdatePidFile(icinga::String const&, int) (+0xe7) [0x7fec91f5de87] (application.cpp:671)
(3) libbase.so: icinga::Application::Run() (+0xd9) [0x7fec91f627f9] (basic_string.h:287)
(4) icinga2: Main() (+0x740c) [0x4250cc] (??:0)
(5) icinga2: main (+0x25) [0x4252a5] (??:0)
(6) libc.so.6: __libc_start_main (+0xfd) [0x7fec9023dead] (libc-start.c:276)
(7) ./sbin/icinga2() [0x41dbf9]
[icinga::ContextTrace*] =
***
* This would indicate a runtime problem or configuration error. If you believe this is a bug in Icinga 2
* please submit a bug report at https://dev.icinga.org/ and include this stack trace as well as any other
* information that might be useful in order to reproduce this problem.
***
Aborted

In dieser Fehlermeldung sind soviele Informationen versteckt, dass es für den Benutzer schon teilweise schwierig wird, überhaupt die eigentliche Fehlermeldung (“Could not open PID file ‘/home/gbeutner/i2/var/run/icinga2/icinga2.pid'”) zu finden. Und trotzdem fehlt hier eigentlich eine ganz entscheidende Information: Warum ist das Öffnen der Datei denn eigentlich gescheitert?
Für mich als Entwickler sind solche Fehlermeldungen natürlich sehr praktisch: Ich weiss genau – abgesehen vom fehlenden Fehlercode, in welcher Zeile und zu welchem Zeitpunkt der Fehler aufgetreten ist; die Fehlermeldung beinhaltet die Pfade zu wichtigen Dateien. Diese Details helfen mir, das Problem zu reproduzieren bzw. evtl sogar direkt anhand des Stacktraces zu finden.
Die beiden Beispiele verdeutlichen einige Eigenschaften, die Fehlermeldungen haben sollen, um den Benutzer bei der Fehlersuche zu helfen:

  • Sie sollten kurz und einfach zu verstehen sein (keine Stacktraces, Klassennamen, o.ä.)
  • Sie sollten alle wichtigen Informationen enthalten (Dateinamen, Fehlercode)
  • Sie sollten den Benutzer in Richtung der Problemlösung leiten (z.B. bei EPERM -> Hinweis auf Datei-Berechtigungen)
  • Zusätzlich sollten die für Entwickler wichtigen Informationen aber trotzdem bereitgehalten werden; vielleicht als Referenz auf eine separate Log-Datei, die dann auch gerne seitenlange Stacktraces enthalten kann

Dass bei den Logmeldungen von Icinga 2 dieses Ideal noch nicht erreicht ist, haben wir im Bugtracker zusammengefasst und arbeiten fleissig daran, dies noch zu verbessern. Wer beim Testen noch auf etwas unhandliche Fehlermeldungen stößt, sollte dazu Issues erstellen, damit wir diese für die Beta 2 noch anpassen können.

Produktverteilerdatei – Fehler im Mac App Store beheben

Schon seit einigen Tagen versuche ich im Mac App Store die neue Version von TweetDeck zu “kaufen”, was aber nicht klappen. Denn ich bekomme die folgende, wenig aussagende Fehlermeldung:

“Ihr Kauf konnte nicht abgeschlossen werden. Die Produktverteilerdatei konnte nicht überprüft werden. Möglicherweise ist sie beschädigt oder wurde nicht ordnungsgemäß signiert.”

Zuerst dachte ich, dass es sich vielleicht nur um einen temporären Fehler handelt oder Apple da gerade etwas wartet und vielleicht nur vergessen hat ein gelbes PostIt dranzukleben. Leider hat sich der Fehler aber nicht selbst behoben und auch Google hat nichts brauchbares ausgespuckt, so dass ich mich selber auf die Suche begeben musste.
Folgendes hat mein Problem dann behoben. Der Fehler wird inkl. Details geloggt. Dort kann man rausfinden, wo diese ominöse Produktverteilerdatei eigentlich liegt und dann alle betroffenen Dateien einfach löschen. Der App Store legt die dann beim nächsten Start einfach neu an. Hier die Vorgehensweise im Einzelnen:

  1. Am besten zuerst alle Programme schließen, damit im Logfile nicht so viele Meldungen durchscrollen
  2. Im Finder “konsole” eingeben und das Programm Konsole starten
  3. Im linken Menü “Alle Systemmeldungen” auswählen
  4. Den App Store öffnen und nochmal versuchen das betroffene Programm zu kaufen
  5. Im gleichen Moment oder wenige Sekunden später müsste die Fehlermeldung auch im Log auftauchen:
    13.12.11 13:40:22,342 App Store: FRPurchaseManager: Preflight operation for 485812721 failed with error: Error Domain=com.apple.appstore Code=0 “Die Produktverteilerdatei konnte nicht überprüft werden. Möglicherweise ist sie beschädigt oder wurde nicht ordnungsgemäß signiert.”  (usw.)
  6. Die Meldung kann man mit einem Klick auf das kleine Dreieck aufklappen
  7. Weiter im Text findet sich dann eine URI mit dem Hinweis auf die genaue Lage der Date im Dateisystem:
    “Cannot create PKProduct from “file://localhost/var/folders/c3/->
    g01fg00s6wxf0rlp4y171k_m0000gn/C/com.apple.appstore/485812721/preflight.pfpkg”
  8. Jetzt weiss man wo die Produktverteilerdatei liegt und kann sie inkl. der anderen Cache Dateien einfach löschen. Entweder im Terminal oder wenn man sich nicht so auskennt über den Finder:
    • Finder normal starten
    • CMD+SHIFT+G drücken und dann /var/folders/ eingeben
    • Durchklicken bis zu “com.apple.appstore”
    • Markieren und zum Löschen CMD-BACKSPACE drücken
    • Papierkorb leeren
  9. Als letztes nur noch den App Store neu starten und die App kaufen. Voilà
Julian Hein
Julian Hein
Executive Chairman

Julian ist Gründer und Eigentümer der NETWAYS Gruppe und kümmert sich um die strategische Ausrichtung des Unternehmens. Neben seinem technischen und betriebswirtschaftlichen Background ist Julian häufig auch kreativer Kopf und Namensgeber, beispielsweise auch für Icinga. Darüber hinaus ist er als CPO (Chief Plugin Officer) auch für die konzernweite Pluginstrategie verantwortlich und stösst regelmässig auf technische Herausforderungen, die sonst noch kein Mensch zuvor gesehen hat.

World of Errors I

guru

Wer kann sich an diese Fehlermeldung noch erinnern? Erklärung gibt es in der Wikipedia.

Julian Hein
Julian Hein
Executive Chairman

Julian ist Gründer und Eigentümer der NETWAYS Gruppe und kümmert sich um die strategische Ausrichtung des Unternehmens. Neben seinem technischen und betriebswirtschaftlichen Background ist Julian häufig auch kreativer Kopf und Namensgeber, beispielsweise auch für Icinga. Darüber hinaus ist er als CPO (Chief Plugin Officer) auch für die konzernweite Pluginstrategie verantwortlich und stösst regelmässig auf technische Herausforderungen, die sonst noch kein Mensch zuvor gesehen hat.