IML Appmonitor: Code-Update für PHP8+
Der IML Appmonitor dient der Ergänzung unseres Systemmonitorings. Aus Sicht einer Applikation werden Prüfungen vorgenommen, die in ihrer Summe eine Aussage treffen, ob eine Applikation gerade lauffähig ist. Sei es die Verfügbarkeit von Ressourcen, APIs oder Datenbanken, Schreibzugriffe auf Upload Folder. Auch sollte man umgekehrt schützenswerte Informationen prüfen, ob diese bei gewöhnlichen Http-Anfragen eben nicht ausgeliefert werden und ein 40x Fehlercode melden.
Man kann Prüfungen miteinander verknüpfen, z.B. muss eine Konfigurationsdatei lesbar sein - die z.B. Credentials für eine Datenbank besitzt - dann ist die Prüfung der Datenbankverbindung von der Lesbarkeit der Konfigurationsdatei abhängig. So kann man einen Abhängigkeitsbaum zu visualisieren, der einem Projektmanager ein klareres Bild zu einer Störung vermitteln kann.
Im Zuge des Updates unserer PHP-Applikationen habe ich den PHP-Code unter PHP 8.3 aktualisiert:
- Bisher ist alles untypisiert gewesen. In Klassen wurden Variablen, Parameter von Methoden und deren Returncode typisiert (also eine Angabe, ob eine Variable ein String, Integer, Array, Objekt, … ist). Das hilft dem Compiler bei Optimierungen und sichert den Code ab. Ist aber auch - bei mechanischem, visuellen Ersetzen auch etwas fehleranfällig.
- PHPDoc wurde in allen Methoden geprüft - da gab es doch viele Kommentar-Sektionen, die nicht mit dem Code übereinstimmten
- Alle Arrays und Hashes wurden auf die verkürzte Array-Schreibweise umformatiert.
- Die Markdown-Hilfedateien wurden überarbeitet
Kurz: ohne Funktionalitätsgewinn wurden ein paar tausend Zeilen in 70+ Dateien geändert und heute gemergt: https://github.com/i … onitor/pull/88/files
Aber dem Programmcode tut es sicher gut, gelegentlich auf einen aktuelleren Stand gehoben zu werden.
Gleichartiges widerfuhr letzte Woche dem Code unseres Intranets.
Weiterführende Informationen:
- 🧾 Sourcecode: https://github.com/iml-it/appmonitor
- 📜 License: GNU GPL 3.0
- 📗 Docs: https://os-docs.iml.unibe.ch/appmonitor/
Daux auf Manjaro installieren
In Manjaro Linux gibt es Pakete - darunter auch PHP und ist schnell installiert. Den Composer nachzuschieben ist ein Nobrainer und dann kann man
composer global require daux/daux.io
aufrufen, um Daux lokal zu installieren. Das klingt alles straight forward. Wie bei allen anderen Distros mit Paketmanagement auch.
Es gibt jedoch unter Manjaro ein ABER: ein “daux generate” verweigert seinen Dienst, sobald man das Generieren einer Offline-Javascript Suche in einem Doc Projekt aktiviert hat. Es fehle die Funktion iconv. Das entsprechende PHP-Paket kann man installieren, aber dann wird der Apache httpd gleichsam installiert.
Daher nochmal Reset und von vorn. Wie bekommt man Daux nun inkl. Suche zum Laufen? Also, ohne einen Webserver installieren zu müssen und rein mit PHP-CLI?
(1) PHP-Quelle einbinden
Es gibt neben Manjao-Paketen weitere Quellen, die man einbinden kann.
https://aur.archlinux.org/pkgbase/php82
Man folge der dortigen Anleitung:
(a) als root in der /etc/pacman.conf eintragen
[home_el_archphp_Arch] Server = https://download.opensuse.org/repositories/home:/el:/archphp/Arch/$arch
(b) als root in der Shell:
key=$(curl -fsSL https://download.opensuse.org/repositories/home:el:archphp/Arch/$(uname -m)/home_el_archphp_Arch.key) fingerprint=$(gpg --quiet --with-colons --import-options show-only --import --fingerprint <<< "${key}" | awk -F: '$1 == "fpr" { print $10 }') pacman-key --init pacman-key --add - <<< "${key}" pacman-key --lsign-key "${fingerprint}"
Und zum Aktualisieren der Paket-Datenbank
pacman -Syy
(2) PHP Pakete installieren
Man installiere diese Pakete:
php82 php82-cli php82-iconv php82-mbstring php82-openssl php82-phar
Jene werden benötigt, um den Composer zu compilieren.
(3) php verfübar machen
Noch schnell ein Zwischenschritt.
Nach Installieren von PHP82-cli wird bei Eingabe “php” auf der Shell kein Binary gefunden. Das, weil es “php82” heisst - Daux wird aber nach “php” suchen. “which php82” verrät uns, dass es unter /usr/bin liegt (oder aber man schaut in die Paket-Details).
Wie lösen wir das? Ich würde zu einem Softlink greifen.
Man kann sich mit “echo $PATH” ansehen, welche bin-Verzeichnisse verfügbar sind. Weil ich bei mir am Rechner nur allein mit meinem lokalen User arbeite, lege ich den Softlink unter meinem $HOME an. Soll es global für alle User funktionieren, würde ich den Softlink in /usr/bin/ anlegen.
cd ~/bin/ ln -s /usr/bin/php82 php
Test: Wenn anschliessend “php -v” nun etwas ausgibt, dann passt es.
(4) PHP Composer 8.2 installieren
Nun kann man den php82-composer aus den AUR installieren. AUR muss man folglich im Paketmanager aktiviert haben.
(5) Daux installieren
composer82 global require daux/daux.io
Also … statt “composer” ist “composer82” entsprechend der PHP-Version aufzurufen.
(6) Daux verwenden
daux generate
… voila: funktioniert nun inkl. Suche! Viel Spass!
Weiterführende Links:
- daux.io (en)
- Arch :: Package Base Details: php82 (en)
ahCrawler läuft auf PHP 8.3
PHP hat kürzlich die Version 8.3 herausgegeben [1] - und gleichzeitig erhält PHP 8.0 keinerlei Support mehr.
Mein Werkzeug ahCrawler [2], [3] - eine Suchmaschine für diie Webseite und Webseiten-Analysetool - darf hier nicht aussen vor sen. Sie wurde in einem Docker-Container mit der neuen PHP Version 8.3 durchgetestet … und für gut befunden.
Die vorherige Version lief bereits mit dem aktuellen PHP - es gab im Minor-Update nur kleine, nichtfunktionale Updates, die wie immer via Web UI oder Git pull oder Updater eingespielt werden können.
Die Suchseite hinter www.axel-hahn.de ist bereits aktualisiert worden.
Weiterführende Links
Pimped Apache Status - PHP 8.2 kompatibel
Der Pimped Apachestatus ist ein Webtool, dass die etwas schwer verdauliche Apache Serverstatus Page aufbereitet. Es gibt verschiedene Ansichten, sortier- und filterbare Tabellen und Graphen. Das ganze funktioniert nicht nur für einen einzelnen Server, sondern auch für mehrere Webhosts, z.B loadbalante Webeiten.
Am Wochenende gab es ein Update, in dem einige Vendor-Bibliotheken aktualisiert wurden.
Da die als kompatibel bestätigte Version 8.0 alsbald ausläuft, wurde es mit neueren PHP Versionen getestet. Es ist nunmehr PHP 8.2 kompatibel.
Zum Aktualisieren meldet sich der Updater. Bei Installationen mit git bitte git pull verwenden.
Weiterführende Links:
Update ahCrawler v0.156
Ich habe ein Update des ahCrawler veröffentlicht.
In diesem Release kamen hinzu
- meine Docker-Entwicklungsumgebung wurde aufgenommen
- die Dokumentation wurde neu geschrieben als Markdown und ebenfalls im Repo aufgenommen
- es gibt zahlreiche Updates im Bereich der Suche im Backend und Frontend.
Das führte dazu, dass die Verzeichnisstruktur des Repos verändert werden musste. Alle bisherigen Files konnten unterhalb Webroot in einem beliebigen Unterverzeichnis geklont werden. Nun wurden alle Webfiles in den Unterordner “public_html” verschoben. Git basierte Installationen machen eine laufende Instanz mit einem Update kaputt, aber ich hoffe, ich habe es gut genug dokumentiert.
weiterführende Links:
- Github: Sourcecode
- Docs (axel-hahn.de): Changelog
- Docs (axel-hahn.de): Upgrade auf v0.156 (Zielseite wurde wg. veralteter Version entfernt)
- Twitter-Post zum Update
- Mastodon: Tröööt zum Update auf fosstodon.org
PHP-Klasse ahLogger aktualisiert
Ich habe mal diese Loggerklasse geschrieben, um in einer PHP-Anwendung Dinge während eines Client-Requests zu debuggen. Ich zeichne Meldungen auf, die mit einem Status (OK, Info, Warnung oder Fehler) versehen werden. Auch kann man übergabe-Parameter und sonstige Variablen dort reinblasen.
Eine Rendering Funktion zeichnet eine Tabelle mit allen Meldungen ans untere Ende der Webseite. Alles kein Hexenwerk.
Wenn man schon Meldungen einsammelt, dann wird auch ein Zeitstempel getrackt. Und wenn man Zeitstempel hat, dann kann man die Zeitdauer von einzelnen Aktionen messen und tracken: wie lange läuft eine Datenbank-Abfrage, ein Exec oder eine andere Aktion - das bekommt man gratis dazu: in einer Spalte der Ausgabetabelle wird das Delta zur letzten aufgezeichneten Meldung ausgegeben.
Ein Div rechts oben zeigt die Verarbeitunsdauer des Requests am Server an und kennzeichnet farblich, ob es eine Warnung oder einen Fehler gab. Man kann von hier auch direkt zu den Einträgen mit Warnung oder Fehler springen.
Mit überschaubarem Aufwand entstand ein hilfreiches Werkzeug zum Debuggen, Messen und Bottlenecks finden.
So wird es gemacht:
Nach dem Initialisieren wird mt der Methode add() beliebig oft je eine Meldung erfasst.
$oLog = new logger(); // Beispiel 1: hilfreiche Daten sichtbar machen $oLog->add("INFO: all GET params: <pre>" . print_r($_GET,1) . "</pre>"); $oLog->add("INFO: all POST params: <pre>" . print_r($_POST,1) . "</pre>"); // Beispiel 2: Zeiten messen geht implizit - durch Schreiben einer neuen Logmeldung $oLog->add("start db request"); $sSql='select id, label, description from mytable;'; // ... make your query $oLog->add("sql query finished: " . $sSql);
Eine render() Methode gibt am Ende das Ergebnis aus.
// die Ausgabe ... aber natürlich nicht für jeden Seitenbesucher if ($bDebugIsEnabled){ echo $oLog->render(); }
Was ist neu?
- Wenn ich bereits Zeiten mitschreibe, ist das Auslesen des Speicherverbrauchs fast ein Nobrainer. So sieht man, wo wärend der Aktionen eines Seitenaufrufs der Speicherverbrauch wie wächst.
- Balken visualisiern nun den Speichrverbrauch und die gemessenen Zeiten.
- Emoji Icons machen die Ausgabe etwas locker.
So sieht es aus:
weiterführende Links:
IML CI Server von PHP 7 auf PHP 8.1 portiert
Der IML CI Server ist ein seit 2015 produktives Werkzeug, mit dem bei uns am Institut gut 50 Projekte ausgerollt werden. Bediente Programmiersprachen für unsere Projekte sind PHP, NodeJs und Ruby - aber eine Zielsprache ist nicht limitiert. Der CI Server erzwingt den Workflow der Installations-Reihenfolge über Preview -> Stage -> Live.
Einschub:
F: Warum beschreibe ich das hier auf einer privaten Webseite?
A: Opensource wird an unserem Institut in einem Ausmass genutzt, dass ohne Opensource Produkte bei unserem Betrieb so ziemlich nichts ginge. Aber auch hauseigene Opensource-Projekte werden auf unserer offiziellen Seite ferngehalten. Begriffe, wie “Opensource” oder “GPL” sind genauso inexistent, wie “mein” hier beschriebener CI Server in der Rubrik Software-Entwicklung.
Wie das Rollout im Groben funktioniert:
Build
- Mit einem Git clone wird der Sourcecode des Projektes in ein temporäres Build-Verzeichnis geholt.
- Das Projekt kann mit einem definierten Hook-Skript Aktionen triggern, um Module nachzuladen, etwas compilieren, Javascript+CSS minimieren … was auch immer
- Was dann noch im Build-Verzeichnis überbleibt, wird zu einem Archiv zusammengepackt und eine Metainfo-Datei angelegt.
- Der CI Server kann die Installation triggern. Mitgeliefert werden 2 Plugins für einen SSH-Aufruf und Ansible AWX. Damit etwaige Tools die Installation starten können - und ohne Zugriff auf den CI-Server im internen Netz haben zu müssen, kann man das Paket per Rsync zu mehreren Zielsystemen syncen, z.B. zu einem Puppet Master oder einem abgesicherten Software-Download-Server (das ist ein seperates Open Source-Projekt).
Installation auf der ersten Phase (Preview)
- Das Paket wartet in der Queue im Modus “zur Installation bereit”. Die Queue besitzt eine zeitliche Freigabe. Man kann erzwingen, dass eine Installation beipielsweise nur von Montag bis Donnerstag im Zeitfenster 14:00-15:00 Uhr erfolgen darf.
- Im Projekt-spezifischen Setup ist festgelegt, ob das Rollout per SSH oder AWX mit entsprechender Parametrisierung erfolgt … und auch welche Zielsysteme existieren. Das AWX Rollout-Plugin holt sich per API die Templates, Inventories und Playbooks vom AWX Server, die in den Prohjekteinstellungen als Dropdown zur Auswahl stehen. Nach einem Build wird das Rollout-Plugin auf die erste Projekt-Phase angewendet, um das Projekt zu installieren.
- Die Implementierung der Installation ist keine Komponente des CI Servers. Es gibt aber eine Bash-Implementierung für ein Installations-Werkzeug (ebenfalls ein separates Opensource Projekt).
- Unsere Installation umfasst … (sicherer) Download des Software Archivs … Entpacken dessen … Start eines Hook-Skripts zur Installation und anderen Aktionen (Cleanup des Cache, Restart von Services) … Generieren von systemspezifischen Konfigurationsdateien mittels Templates
- Feedback an den CI Server, damit dieser weiss, wie weit das Paket ausgerollt wurde.
Rollout auf Stage und Live
Rein technisch ist das identisch mit dem, was zur Installation auf Preview gesagt wurde.
Damit ein Paket von einer zur nächsten Phase freigegeben werden kann, bedingt es die Interaktion - den Klick eines [Accept] Buttons plus Bestätigung, dass man die Featrues und Software-Zustand für OK befunden hat.
Zum Update auf PHP 8.1 habe ich für eine Entwicklungsumgebung mit rootless Docker die benötigte Konfiguration aufgebaut - diese ist im Repository im Unterverzeichnis “docker” enthalten (zuvor habe ich mit einer lokalen Virtualbox-Instanz entwickelt). Das wird Weiterentwicklungen vereinfachen.
Das Update beinhaltet rein die Portierung auf ein aktuelles PHP 8.1 um es auf einem Server mit aktuellesten OS zum Laufen zu bringen. Andere Komponenten, wie Bootstrap 3 sind gnadenlos veraltet und dürfen wohl in naher Zukunft aktualisiert werden.
Screenshots
In der Übersichtsseite aller Projekte kann man filtern, um die Ansicht zum Auffinden “seines” Projektes zu reduzieren.
Ein neuer Build erhält basierend auf dem Hash der Commit ID einen Farbcode. Damit lässt sich optisch darstellen, wie weit ein neuer Build bereits ausgerollt ist. In jeder Phase gibt es [Info] Buttons, die einem Details im Popup aufzeigen.
Erstellen eines neuen Projektes.
Wahlt man ein Projekt, sieht man zunächst eine Seite mit Repo, Archiv (der Builds) und die Phasen des Projekts
In den Projekt-Einstellungen .. Tab Rollout: hier das AWX-Plugin mit den allg. Voreinstellungen. Jedes einzelne Feld lässt sich in jeder der Phasen äbernehmen oder aber nochmals übersteuern.
weiterführende Links:
- Repo: IML CI Server (Opensource; GPL 3.0)
- Docs: IML CI Server auf os-docs.iml.unibe.ch (WIP)
- Repo: IML CI Paket Server (Opensource; GPL 3.0) - Software-Archiv für ein öffentlich zugängliches System, welches nur sichere Downloads mit one time Tokens zulässt
- Docs: IML CI Paket Server auf os-docs.iml.unibe.ch
- Repo: IML CI Deployment Client (Opensource; GPL 3.0) - Bash-Skript zur Installation via IML CI Paket Server, Ondeploy-Hook, Generierung von Konfigurationen aus Templates
- Docs: IML CI Deployment Client auf os-docs.iml.unibe.ch
Update meiner Open source docs
Unter https://www.axel-hahn.de/docs/[POJEKT] habe ich diverse Hilfen für PHP- und Javascript Tools bereitgestellt, die ich mit einem Parser generieren lasse. Jener Ansatz ist etwas älter und länger her - und stellt bereits geraume Zeit so einige meiner Dokumentationen bereit…
Eigentlich suchte ich nach einem mehr generischen Ansatz, um heutzutage in Git übliche Markdown-Dateien in statisches HTML umzuwandeln. Es gibt da diverse Tools, aber ich bin beim PHP-CLI Tool Daux hängengeblieben. Insbesondere, weil ich hier im Gegensatz zu anderen angetesten Werkzeugen keine Extra Konfiguration für einen Navigationsbaum als Config-Datei hinterlegen muss. Auch hat der Entwickler sehr schnell reagiert und auf gemeldete Feature Requests reagiert. Kurz: ich habe nun diverse einzelne Dokumentationen verschiedener Produkte und Klassen mit Daux gebaut. Das sind jeweils statische Verzeichnisse mit statischen HTML-Dateien + Javascript und Css out of the Box in jedem Browser laufen, wenn man sie vom Filesystem oder aber USB-Stick startet.
Was diverse Markdown zu Html Generatoren bieten, ist ein eingebauer Webserver für eine Vorschau. Der hilft beim Schreiben der Markdown-Dateien. Mittlerweile in Markdown Quasi-Standard ist der Support von mathematischen Formeln oder aber Graphen (mermaid.js) - das soweit ich auf Github, Gitlab oder aber lokal im Visual Studio Code per Markdown Preview gesehen habe.
Soweit so gut. Und wenn ich nun zig alleinstehende Dokumentationen habe und eine Index-Seite haben will?
Ich habe dazu einen Ansatz zum Generieren einer Index-Seite wie folgt gewählt:
- ich möchte Gruppen: nach Programmiersprache oder nach einer sonstigen Rubrik
- in jeder Rubrik werden N Projekt-Dokumenationen verlinkt
- … wobei jene referenziert wird als Git-Repository, um diese mit Daux on the fly generieren zu lassen
- … oder aber: weil ich noch meine geparsten Dokumentationen habe: ich kann anderweitig bestehende Dokumentationen ebenfalls einbetten
- die Index-Seite soll flexibel sein und verschiedene Templates/ CSS/ Javascritpt unterstützen
Ich habe dazu ein Bash-Skript geschrieben, das mit jq eine JSON Config-Datei parst und mittels eines Templates die Seitenelemente generieren lässt. Die Flexibilität steckt in den Templates - dese bestimmen, ob es ein
OK, all das ist zu viel Text … so sieht meine Übersichtsseite mit dem Template mit Gruppen und Boxen sieht so aus: Axels Docs
weiterführende Links: (en)
- Axels Docs-Index-Seite
- daux.io Hilfe-generator - Markdown zu HTML
- Github: axelhahn/multidoc-generator
- Statische Hilfe zum multidoc-generator
- Mermaid.js
PHP CLI und FPM-Service: /tmp besser meiden
Ich habe da eine PHP-Applikation, die ein Webinterface besitzt als auch per CLI einige Dinge - z.B. als Cronjob - aufruft.
Beide Arten von Skripten - bei Http Aufruf oder aber CLI - durchliefen dasselbe Init-Prozedere und referenzierten ein und dasselbe File.
$this->sTouchfile = sys_get_temp_dir() . '/some_file.tmp';
Oder besser: ich hatte es zumindest gemeint. sys_get_temp_dir() wurde auf dem Linux-System als “/tmp” aufgelöst. Also optisch war es dieselbe Datei: /tmp/some_file.tmp - aber Das Webinterface erkannte eine Aktion auf CLI Seite nicht … und umgekehrt das CLI nicht eine Schreibaktion aus dem Webinterface.
Bis ich dann mal auf die Idee kam und mir mit einem per Http aufgerufenem Skript eine spezifische Datei in /tmp/ anlegte und diese mal im Filesystem suchte. Unter dem PHP-FPM Service war als /tmp/ jenes “tmp” Verzeichnis verwendet worden:
/tmp/systemd-private-d1b7cf65cce54d4ca9f98c49cca1887f-httpd.service-NoEzTN/tmp/
Das hat mir das ungewöhnliche Verhalten auch sofort erklärt.
Man merke: /tmp sollte man meiden, wenn man gemeinsame Daten per http als auch CLI Daten teilt. Ich habe in meiner Applikation von sys_get_temp_dir() auf ein “tmp” unterhalb [Approot] umgestellt…
weiterführende Links:
IML Appmonitor ist nun PHP 8.1 kompatibel
Der Appmonitor ist eine PHP-Applikation mit geringstmöglichen Anforderungen. Mit dieser lassen sich andere (Web-)Applikationen in einem Webfrontend überwachen und bei Statuswechsel Notifikationen per E-Mail und Slack an die am Projekt beteiligten Personen auslösen.
Das Applikationsmonitoring ergänzt unser System-Monitoring, weil es die applikationsseitigen Checks aus Sicht der Applikation und mit den Rechten der Applikation ausführt.
Der Appmonitor ist Freie Software, Opensource und untersteht der GNU GPL 3.0.
Nach gefühlt 2 Jahren habe ich am IML Appmonitor weitergecodet. Es sollte PHP 8 kompatibel werden. Und weil soeben PHP 8.1 erschienen ist, wurde es nun auch für ebenjene Version 8.1 fit gemacht:
Tadaaa: der Appmonitor ist die erste PHP 8.1 kompatible Opensource Applikation unseres Instituts :-)
Zudem wird die Plugin-Unterstützung vorangetrieben, es kam eine grafische Darstellung der Checks in einem ersten Wurf hinzu und die Möglichkeit, die Checks nach vorgegebenen Gruppen zu clustern. Die Notifikation eines Fehlers erfolgt nicht beim ersten Auftreten, sondern wird erst bei der 3. Wiederholung ausgelöst.
Ich bin gerade motiviert, weitere Updates einzubringen und nachzuliefern. Es gibt beispielsweise vorgefertigte Checks für einige PHP-Applikationen, wie Wordpress, Ilias LMS, Concrete5 und Matomo. Diese befinden sich in einem separaten Repository und werden in Kürze in das Repo integriert.
weiterführende Links: