
Bei DoiT International nutzen wir Google BigQuery intensiv als Analyseplattform für reOptimize (heute Teil von DoiT Cloud Intelligence™) – unsere Plattform zur Kostenoptimierung der Google Cloud Platform.
Google BigQuery ist ein hervorragendes serverloses Tool, um große Datenmengen per Standard-SQL abzufragen. Das Preismodell richtet sich nach dem während einer Abfrage gescannten Datenvolumen, und es lassen sich bis zu 50 Abfragen parallel ausführen (gecachte Abfragen zählen nicht).
Sobald in Ihrer Organisation mehrere Teams zugreifen, brauchen Sie einen Überblick darüber, was gerade läuft. Out of the Box gibt es jedoch keine Möglichkeit, die aktuell laufenden Queries einzusehen – und genau hier kommt bqtop ins Spiel.

Unser Ziel war ein schlankes Kommandozeilen-Tool und zusätzlich eine Web-App, mit denen sich die aktuell laufenden Queries und ein Stück Historie einsehen lassen. Für die nötigen Daten haben wir eine vollständig serverlose Pipeline gebaut, die alle Informationen direkt an unsere Anwendung liefert.
Starten wir mit der "Server"-Seite
Zuerst legen wir einige Stackdriver Logs Sinks an, um die BigQuery-Logs nach Google Pub/Sub zu exportieren. Wir erstellen zwei Sinks – der erste filtert die Log-Meldungen, die den Start einer Abfrage signalisieren:
resource.type=bigquery_resource protoPayload.methodName=jobservice.insertund der zweite ist für die abgeschlossenen Abfragen zuständig:
resource.type=bigquery_resource protoPayload.methodName=jobservice.jobcompletedJeder Sink schreibt seine Daten in ein eigenes Pub/Sub-Topic – bqtop-running-jobs und bqtop-finished-jobs.
Jetzt, da die Daten aus den Logs in Pub/Sub fließen, müssen sie in eine Datenbank wandern, auf die später Web-App und CLI zugreifen. Für diesen Use Case wollten wir etwas Schlankes, aber Leistungsfähiges: direkt vom Client lesen können, ohne ein vollwertiges Backend bauen zu müssen, plus Benachrichtigungen bei neuen oder geänderten Daten, damit wir die Datenbank nicht ständig pollen müssen. Googles Firebase war hier die naheliegende Wahl.
Um die Daten aus Pub/Sub in die Firebase-Datenbank zu bringen, setzen wir Firebase Cloud Functions ein. Wir lauschen auf neue Events der Pub/Sub-Topics und schreiben sie anschließend in die Datenbank.
https://gist.github.com/avivl/30d92a579abd48dd4b3a9131b7f6abfb
Die Daten landen in zwei getrennten "Tabellen" der Datenbank – eine für laufende, eine für abgeschlossene Jobs. Sobald ein Job fertig ist, entfernen wir ihn aus der Tabelle der laufenden Jobs. Zusätzlich haben wir ein paar Funktionen ergänzt, die auf Änderungen in den Daten reagieren.
https://gist.github.com/avivl/58dbe67e6ade2b45f89e5a5d698c3dd3
Sobald ein Event mit neuen Daten in der Referenz der abgeschlossenen Jobs eintrifft, suchen wir in den Referenzen der laufenden Jobs nach einem Event mit derselben jobId und löschen es dort.
https://gist.github.com/avivl/c16af302a09a338f41480a11689a10d9
Für mehr Performance haben wir zusätzlich einen Index angelegt (das passiert in der Datei database.rules.json).
https://gist.github.com/avivl/7ab33806e5d8da4caf62b9a57778433a
Und jetzt zur "Client"-Seite
Nachdem die "Server"-Seite steht, geht es weiter zum Client. Wir wollten sowohl ein Kommandozeilen-Tool für unsere Engineers als auch eine Web-App, die auf dem Dashboard-TV im Büro läuft.
Die Kommandozeilen-App ist eine kleine Python-Anwendung, die für die gesamte UI-Steuerung auf curses setzt. Als Wrapper für die Firebase-API nutzen wir pyrebase. Wie oben beschrieben wollen wir die Datenbank nicht permanent pollen, sondern bei Änderungen benachrichtigt werden. Dafür verwenden wir zwei Datenbank-Streams, die bei jeder Änderung aufgerufen werden.
https://gist.github.com/avivl/8ea27a7f98feb1d8735151ae3ba97bff
Sobald die Handler-Funktion aufgerufen wird, können wir die Daten abrufen und dem Nutzer anzeigen.
Für die Web-App setzen wir auf React und das Firebase JavaScript SDK, um die Daten aus der Datenbank zu lesen und auf der Seite zu visualisieren.
Kurz gesagt: Wir haben eine elegante Pipeline gebaut, die BigQuery-Logs an Google Pub/Sub schickt, sie per Cloud Functions verarbeitet und schließlich in der Firebase Realtime Database ablegt – ganz ohne eigene Server und mit minimalem Coding-Aufwand.