Appmonitor Server Webgui auf AdminLTE portiert

Mittwoch, 6. März, 2019

Ich weiss ja auch nicht, was mich vor ein paar Jahre geritten hat, Oberfläche und CSS von Hand und selbst erstellen zu wollen. Weil es schlank ist. Aber eben nicht produktiv.

Nun habe ich die GUI auf AdminLTE portiert - und mir für die benötigten Elemente in AdminLTE die notwendigen Abstraktionen geschrieben. Nun ist es deutlich aufgeräumter!

GUI-Kram kann schon ziemlich lästig sein. Ich bin froh, bin ich damit durch. Nun kann ich mich wieder auf das Implementieren echter Features konzentrieren.

2019-03-06-appmonitor-01.png 2019-03-06-appmonitor-02.png 2019-03-06-appmonitor-03.png

weiterführende Links:

  1. Github: IML Appmonitor
  2. AdminLTE Demo Seite
  3. Docs: os-docs.iml.unibe.ch/appmonitor/

Erstes Tutorial mit OBS: Installation Pimped Apache Status unter Lubuntu

Samstag, 27. Oktober, 2018

Ich hatte, mal irgendwann OBS auf meinem Rechner installiert … seinerzeit für einen recht banalen Zweck (Vollbild-Streaming zu Youtube) … und jenes geriet fast in Vergessenheit, weil nie wieder gebraucht.
Bis - ja bis eines wunderschönen Tages jemand in unserem Institut meinte, “… mit OBS kann ich für eine Demo sehr einfach Bild-Kompositionen auf andere Bildschirme streamen…”. Es sei einfach und verbirgt viele komplexe Einstellungen, zu denen man aber auch kommt.

Dies war der Wink mit dem Zaunpfahl, das Werkzeug gleichen Abends nochmals hervorzukramen: Man kann mehrere Bildschirmszenen ertsellen und dazwischen umschalten? Diese auch speichern? Und statt streamen vielleicht auch ein Video aufzeichnen?

Ich habe mich zu Beginn wohl zu initial wenig auf das Werkzeug eingelassen. Die Einstiegsoberfläche ist halbwegs einfach. Sobald man aber irgendeine Einstellung bearbeitet, wird man mit zahlreichen Optionen regelrecht eingedeckt. Das Speichern der erstellten Szene habe ich gar nicht gefunden, weil ich es als “Pojekt” links oben im ersten Menüpunkt erwartet hätte. Man muss sich wirklich erst etwas genauer umsehen.

Weil ich schon immer mal ein Tutorial mit Aufzeichnung des Bildschirminhaltes machen wollte, habe ich mich nochmals hingesetzt und probiert.
Als Erstlingswerk entstand ein Installationsvideo für mein Monitoring Werkzeug Pimped Apache Status.

2018-10-27-obs.png

Das Haupfenster ist spartanisch … aber hat es in sich

  1. links unten: “Szenen” - eine Liste mit verschiedenen Settings: Start-Bildschirmseite mit Text, dann eine oder mehrere mehrere mit Interaktionen, eine Outro-Szene.
  2. links unten 2: “Quellen” - pro Szene kann man ein Setup von Quellen platzieren. Ein Bild oder Programmfenster, Webcam oder Videoquelle, Text - alle Elemente kann man skalieren und verschieben und so beliebig anordnen. Die Quellen kann man in mehreren Szenen verwenden (verlinken) - damit werden Änderungen eines Textes oder einer Farbe in allen Szenen übernommen.

OBS zeichnet die Szenen-Umschaltung, die ich manuell gesteuert habe (Anm.: man kann dies auch automatisieren) und die in einer Szene eingebetten Bildschirmaktionen als eine Video-Datei auf.
Nach der Aufnahme war das per Webcam aufgezeichnete Audio zu leise - das musste noch normalisiert werden. Und das Video nochmals encodet.
Weil ich noch zusätzlich einige Annotationen einbringen wollte, z.B. weitere Texte und Hervorhebungen in der Ausgabe auf der Konsole, wurde noch ein 2. Video-Bearbeitungswerkzeug herangezogen.

2018-10-27-vsdc-video-editor.png

Und dann die Videodatei ein drittes Mal encodet. Davon wird die Videoqualität nicht besser. Hier habe ich noch Potential für Optimierungen.
Aber dann ging es “sogleich” auf Youtube.

Voila:

weiterführende Links:

  1. obsproject.com OBS Studio (Free and open source software for video recording and live streaming)
  2. videosoftdev.com VSDC Free Video Editor
  3. Axels Webseite - Docs Pimped Apache Status Get started - hier ist das Youtube Video eingebunden

Datenbank-Optimierung - mein Highlight der Woche

Sonntag, 18. Februar, 2018

Bei meiner Arbeit an der Uni Bern war ein Grossteil der Zeit in die Optimierung von Datenbank-Zugriffen geflossen. Das betraf hauptsächlich ein System für ein Portal für Dozierende und Studierende mit Stundenplänen, Kurseinschreibungen, Feeds zu etlichen Themen und nach Studienjahr getrennt, Kalendersynchronisation von personalisierten Kalendern uvm. Jenes Portal ist uralt und wurde einmal mit PHP4 entwickelt und sollte abgelöst werden. Wurde es aber nicht, sondern es wurde vor vielen Jahren mühsam unter PHP5 lauffähig gemacht, aber der Code blieb noch immer zumeist prozedural, mit vielen Includes und gespickt mit allen erdenklichen Highlights an Programmiersünden, sei es Wartbarkeit, Caching/ Performance, SQL-Injection oder Verständnis von Algorithmen und Gestaltung von Datenbankabfragen. Seit dem ersten Ablösetermin sind nun 8..9 Jahre vergangen … aber Herbst 2019 wird es endlich(!!) abgelöst. Heisst aber: bis dahin muss es weiter am Leben erhalten werden.

Es wurden 5 Applikationsteile, die “am meisten weh tun” ausgemacht und jene optimiert. Letzten Dienstag wurde es eingespielt. Doch, es hat sich gelohnt - da ist so ein markanter Abfall:

2018-02-18-dbperformance-queries-by-week.png

Man könnte meinen: da ist was kaputt. Aber nein: es funktioniert genau gleich!!
Ich hoffe, ich kann euch mit diesem Praxis-Beispiel motivieren: macht einmal eine Performance-Analyse und schaut genauer auf die Top 3!

[Weiterlesen…]

Texte anhand einer Quelle einfärben

Sonntag, 4. Februar, 2018

Meine Nachrichten-Feeds benennen die Nachrichten-Quelle und färben sie ein. Es entsteht eine “bunt” eingefärbte Quelle, bevor deren Meldungs-Überschrift genannt wird.

Und wie funktioniert es, dass “Tagesschau”, “Spiegel” oder “Heise” jeweils spezifisch eingefärbt sind?

2018-02-04-rssnews.png

Naja, der Text - also String - der Quelle wird mit einer MD5 Funktion gehasht. Dann erhält man so einen Hexcode aus einem vorgegebenen String.

Wenn man sich vom Beginn des Hex-Strings jeweils die aufeinanderfolgenden 2..3 Stellen herausgreift, kann man diese dem Anteil für rot, grün und blau zuordnen.
Damit der Hintergrund und Vordergrund relativ zueinander passen, definiere ich für beide einen eine Range von..bis. Der ermittelte Wert aus dem Hash wird relativ zum von-bis-Range für Vordergrund und Hintergrund eingeordnet.

Und das ist der zugehörige PHP-Code:

/**
 * return html code for a span with background color based on a checksum of the given text
 * @param string $sText      text that is used for checksum; if false it returns a gray box
 * @param string $sContent   optional: text to show
 * @return string
 */
function _getChecksumSpan($sText, $sContent = '') {
    if ($sText) {
        // color ranges in decimal values for RGB from ... to
        $iFgStart = 60;
        $iFgEnd = 160;

        $iBgStart = 180;
        $iBgEnd = 240;

        // divider: 3 digits of md5 will be extracted
        $iFgDivider = 16 * 16 * 16 / ($iFgEnd - $iFgStart);
        $iBgDivider = 16 * 16 * 16 / ($iBgEnd - $iBgStart);

        $sHash = md5($sText);
        $sColor = ''
                . 'color: rgba('
                . ($iFgStart + round(hexdec(substr($sHash, 0, 3)) / $iFgDivider)) . ','
                . ($iFgStart + round(hexdec(substr($sHash, 3, 3)) / $iFgDivider)) . ','
                . ($iFgStart + round(hexdec(substr($sHash, 6, 3)) / $iFgDivider)) . ','
                . '1'
                . ');'
                . 'background: rgba('
                . ($iBgStart + round(hexdec(substr($sHash, 0, 3)) / $iBgDivider)) . ','
                . ($iBgStart + round(hexdec(substr($sHash, 3, 3)) / $iBgDivider)) . ','
                . ($iBgStart + round(hexdec(substr($sHash, 6, 3)) / $iBgDivider)) . ','
                . '1'
                . ');'
        ;
    } else {
        $sColor = "color: #888; background: #ccc;";
    }
    return '<span style="' . $sColor . '; border-left: 0.8em solid; padding: 0.1em 0.4em 0.1em 0.3em ;">' . ($sContent ? $sContent : ' ') . '</span>';
}

weiterführende Links:

  1. meine RSS-Seite: Nachrichten

PHP-Funktion: Passwort-Check bei haveibeenpwned.com

Mittwoch, 16. August, 2017

Anbei eine Funktion, die mit der API von haveibeenpwned.com ein Passwort prüft, ob dieses als gehackt gilt.
Wenn die Funktion true zurückliefert, wurde das Passwort gefunden (sprich: wurde gehackt). Diese Funktion kann man z.B. in einer Applikation einbauen, wenn man Benutzer ihr Passwort setzen lässt. Wenn die Funktion true liefert, dann wäre die Benutzereingabe als unsicher zurückzuweisen.

/**
* check password in an online database; it returns true if the password
* was found in the database
*
* @see https://haveibeenpwned.com/API/v2
* @param string   $sPassword   password to check
* @param boolean  $bShowDebug  show debug infos or not (default: false)
* @return boolean
*/
function haveibeenpwned($sPassword, $bShowDebug=false){
   
    // --- make the request
    $sCheckPwUrl='https://haveibeenpwned.com/api/pwnedpassword/'.sha1($sPassword).'?originalPasswordIsAHash=true';
    $context = stream_context_create($opts);
    $sPwReturn = file_get_contents(
            $sCheckPwUrl, false,
            stream_context_create(
                array(
                    "http" => array(
                        "method" => "GET",
                        "header" => "User-Agent: php-check-4-my-password\r\nAccept: application/vnd.haveibeenpwned.v2+json\r\n"
                    )
                )   
            )
    );
    $aRespHeader=$http_response_header;
   
    echo $bShowDebug ? '<pre>'.$sCheckPwUrl.'<br>'
            . 'Header: '.print_r($aRespHeader, 1).'<br>'
            . '$sPwReturn = '.$sPwReturn.'<br>'
            .'</pre>' : '' ;
   
    // --- check result
    $bFound=array_search('HTTP/1.1 200 OK', $aRespHeader)!==false;
    echo $bShowDebug ? (
            $bFound ? 'ERROR: The password was found in the database :-/'
                : 'OK: seems not to been hacked yet :-)'
            ) : '';
    return $bFound;
}

weiterführende Links:

  1. https://haveibeenpwned.com/
  2. haveibeenpwned.com - API

PHP-Klasse cdnorlocal

Dienstag, 25. Juli, 2017

Eigentlich begann es als Abfallprodukt. Ich brauchte da in einer Web-Applikation eine Klasse … und habe halt jene kleine Klasse geschrieben: wenn ein Verzeichnis für eine Bibliothek im Vendor-Verzeichnis lokal existiert, dann wirf eine lokale URL zurück. Wenn nicht, dann eine zu einem CDN Hoster. Sowas packt man an sich als Funktion in einen 3 Zeiler.

Damit kann ich abstrahieren, wo eine benötigte Bibliothek tatsächlich liegt. Mein Produkt-Download wird klein, weil ich Bibliotheken nur extern verlinke, statt mit in den Download zu packen. Soll das Produkt auf einem System ohne Internet-Anbindung verwendet werden, kann man die Bibliotheken aber optional lokal legen und auf einen Internet-Zugang verzichten.

Tja und dann kam mir der Sinn, noch eine Admin dafür zu schreiben: ich will live in einer API nach Bibliotheken browsen, Details einsehen, Versionen wechseln, Bibliotheken zu “mir” herunterladen.

Ach so Versionen … da gibt es bei gefragten Produkten in relativ kurzen Intervallen neue Releases. Sei es jQuery, Font-Awesome, Plugins … eigenlich habe ich selbst gar keine Kontrolle über all jene Updates … und wenn was neu ist, dies in meinen Applikationen zu aktualisieren.

Und wenn man Versionen lokal hat und sie schon mal lokal erfragen als auch remote die aktuellste ermitteln kann … machen wir noch einen Versions-Checker für sämtliche lokal gemachten Bibliotheken auf einmal dazu. Es kam eins zum anderen. Ich glaube, ich habe mal ein Grundgerüst. Das wird später einmal eine gute Hilfe, den Überblick über alle meine Bibliotheken und deren Versionen zu behalten.

Browsing (Rendering der API Such-Abfrage bei CDNJS):

2017-07-25-cdnorlocal-01.png

Details (Rendering der API Abfrage einer Library bei CDNJS):

2017-07-25-cdnorlocal-02.png

Versionscheck: lokal hinterlegte Versionen von Bibliotheken werden mit der online aktuellsten Version verglichen

2017-07-25-cdnorlocal-03.png

weiterführende Links:

  1. Github: cdnorlocal
  2. Docs: https://www.axel-hahn.de/docs/cdnorlocal/
  3. https://cdnjs.com/

PHP 7 und Concrete 5 Upgrade

Samstag, 18. Februar, 2017

Heute wurden live eingespielt: Updates 2er Domains, um zu PHP 7 kompatibel zu werden

  • Concrete 5 wurde aktualisiert: von Version 5.6.x sind alle Inhalte migriert auf v8.1
  • Der Source der Blogs wurde gepatcht
  • Meine Inhaltsseiten von Putzi4Win wurden durch statische Seiten ersetzt
  • In der Suche (ahcrawler) wurde Meedoo aktualisiert
  • Auf den Liveseiten wurde PHP5.5 auf Version 7 umgestellt

UPDATE
Und es kamen noch Updates von

  • jQuery
  • Bootstrap
  • Datatables

hinzu

Das war vielleicht etwas viel auf einmal.
Das Meiste läuft, aber die ersten Tage gibt es sicher noch ein paar Holperer. Seht es mir nach :-)

weiterführende Links:

  1. Concrete 5 concrete5.org (en)
  2. PHP php.net (en)
  3. Meedoo - PHP database framework medoo.in (en)
  4. jQuery Javascript Framework jquery.com (en)
  5. Bootstrap Framework getbootstrap.com (en)
  6. Datatables - jQuery Plugin für filterbare und sortierbare Tabellen datatables.net (en)

Opcache auf WAMP-Server unter MS Windows aktivieren

Sonntag, 27. November, 2016

Auf dem Wampserver für Windows wird die opcache DLL mitgeliefert, ist aber nicht aktiv.
Um es zu aktivieren, muss man die php.ini bearbeiten. Man findet Hinweise, wie die Extension zu aktivieren ist. Mein Fehler war, dass ich per Dateimanager die php.ini im Verzeichnis

C:\wamp\bin\php\php5.5.12\

bearbeitete … was zu keinerlei Resultat führte, weil der Apache Daemon die php.ini aus dem Apache-Verzeichnis anzieht:

C:\wamp\bin\apacheapache2.4.9\bin\php.ini

Also …

Schritt 1:
Mit einem phpinfo() in der Ausgabe prüfen, welches die richtige php.ini ist :-)
Oder direkt im Traymenü unter Php die dortige php.ini zum Bearbeiten anklicken.

Schritt 2:
Die php.ini bearbeiten … in der Sektion “[opcache]” ist die Extension zu aktivieren: die Zeile zend_extension=php_opcache.dll eintragen (sie existiert nicht).
Der Eintrag opcache.enable=1 ist hingegen bereits vorhanden:

(...)
[opcache]

zend_extension=php_opcache.dll

; Determines if Zend OPCache is enabled
opcache.enable=1
(...)

Schritt 3:
Apache neu starten. In der Ausgabe von phpinfo() sieht man dann das zusätzliche Modul … und auch Im Tray-Menü Php -> Php Extensions ist opcache ist das Warnsymbol nun weg.
Wer mag, kann noch einen Viewer wählen, um den Speicherstatus zu prüfen, z.B. ob der zugewiesene Speicher für den Cache korrekt ausgelegt ist.

weiterführende Links:

  1. Github: opcache-status
  2. https://easyengine.io/tutorials/php/zend-opcache/ - weitere Webviewer (en)

Pimped Apache Status Beta

Donnerstag, 8. September, 2016

Ich bin dabei, eine Version 2 meines Monitoring Tools Pimped Apache Status bereitzustellen.

Die bestehenden Analyse-Werkzeuge bleiben 1:1 erhalten. Wichtigste Neuheit ist das Admin-Backend: Hier kann man künftig seine Server und Servergruppen für loadbalancte Webseiten per Webbrowser konfigurieren. Bisher musste man dazu eine Config-Datei bearbeiten.

Die Konfigurationsdateien wurden dazu von PHP-Arrays in reine JSON Dateien überführt. Anm.: zur Umwandlung einer 1.x Konfiguration gibt es eine upgrade.php

Aber einmal in Bildern…

Screenshot 1:

  • Das Default-Skin wird ein wenig farbiger: im Menü oben die Icons und die Tabs in der ersten Sub-Navigation
  • In den Kacheln sind wurde eine Kreisgrafik hinzugefügt. Diese hilft beim Bewerten des aktuell angezeigten Wertes: visualisiert ist er im Vergleich zum Maximum der letzten n Werte. Genaueres sieht man dann beim Mouseover über eine Kachel…
  • In der Subnavigation in rot: hier geht es zum Setup

206-09-08-pimped-apache-status-v2beta-01.png

Screenshot 2:

  • Im ersten Tab ist die Konfiguration der Server. Man legt zunächst eine Gruppe an und kann in dieser beliebige Server hinzufügen.
  • in weiteren Tabs kann man die bestehende Konfiguration einsehen: die Default-Einstellungen und die Custom-Settings.

206-09-08-pimped-apache-status-v2beta-02.png

Der Sourcecode der Beta ist in einem Branch auf Github verfügbar. Längerfristig wird der Sourcecode in Github verwaltet werden. Sourceforge wird dann nur noch als Lese-Instanz von Github am Leben erhalten.

Wenn jemand die Beta testen mag, so freue ich mich über euer Feedback.

weiterführende Links:

  1. Github: Pimped Apache Status (Anm.: Seit Veröffentlichung von Version 2 gibt es keinen Beta-Branch mehr)

Objekt mit boolean Attribute per $.ajax senden

Sonntag, 24. Juli, 2016

Ich habe eine kleine PHP-Applikation, die liest Metadaten aus einem JSON-File.
Diese Daten schreibt PHP-Code in ein Html-Dokument als Javascript-Objekt, damit diese in der Seite verfügbar sind.

echo 'var aMetadata=' . json_encode($o->aMetadata, JSON_PRETTY_PRINT) .';';

Wenn ich im Formular die Daten bearbeite und mein aktualisiertes Javascript ans PHP zurücksende, dann in der Form:

   var aMetadata={'title': 'Hello world' }

    $.ajax({
        type: "POST",
        url: sSaveUrl,
        data: {
            function: "setMetadata", 
            value: aMetadata, // <<<<< meine Metadaten
        }
    }).done(function () {
        // ...
    });

Auf Seite PHP wurde $_POST[”value”] der Methode setMetadata() übergeben:

    public function setMetadata($aNewMetadata) {
        if(!is_array($aNewMetadata)){
            echo "ERROR: not an array";
            return false;
        }
        $this->aMetadata=$aNewMetadata;
        return $this->saveMetadata();
    }

Das klappt soweit, bis … ja bis einmal ein boolean Wert übergeben werden soll. Es werden true/ false Werte als Strings in Form von “true”/ “false” vom $.ajax data-Wert gesendet, wenn man das Objekt direkt übergibt. Dann kann schonmal fies werden, wenn lauter korrupte Datensätze entstehen.

[Weiterlesen…]