{"id":29253,"date":"2026-09-13T22:51:55","date_gmt":"2026-09-13T20:51:55","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=29253"},"modified":"2026-09-13T22:51:57","modified_gmt":"2026-09-13T20:51:57","slug":"logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/","title":{"rendered":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Dieser Beitrag ist im Rahmen der Vorlesung <strong>\u201eSoftware Development for Cloud Computing\u201c<\/strong> entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:<br><a href=\"https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26\">https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26<\/a><br><a href=\"https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops\">https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops<\/a><br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">I. Einleitung<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel war es dieses Semester, einen eigenen, wiederverwendbaren Observability-Stack zu bauen, den wir auch \u00fcber dieses Projekt hinaus einsetzen k\u00f6nnen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit wir diesen Stack aber nicht nur theoretisch aufbauen, sondern auch unter realistischen Bedingungen testen konnten, brauchten wir eine kleine Anwendung, die uns echte Telemetriedaten liefert. Die Idee dazu kam uns bei der \u201eGespeichert&#8221;-Funktion von Google Maps, mit der man Orte, Restaurants oder \u00c4hnliches in eigenen Listen organisieren kann. Genau dieses Prinzip haben wir uns als Vorlage genommen und daraus eine kleine REST-API gebaut, die Restaurants verwaltet und in Listen einordnet. Die Anwendung haben wir bewusst schlank gehalten, damit der Fokus klar auf der Infrastruktur rund um die Anwendung liegt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">II. Zielsetzung und Abgrenzung<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Projektziele:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unser Hauptziel war es, eine wiederverwendbare Projektvorlage zu entwickeln, die den Fokus auf Observability legt,\u00a0also auf Logging, Tracing und Metriken. Uns war dabei wichtig, dass der entstehende Stack nicht fest an unsere konkrete Anwendung gekoppelt ist, sondern sich auch in zuk\u00fcnftigen, containerisierten Projekten wiederverwenden l\u00e4sst. Generell wollten wir uns in diesem Projekt st\u00e4rker mit dem Betrieb von Software auseinandersetzen als mit komplexer Fachlogik, weshalb auch eine automatisierte Qualit\u00e4tssicherung \u00fcber CI\/CD, f\u00fcr uns von Anfang an eine Rolle gespielt hat. Au\u00dferdem ging es uns darum, moderne DevOps-Werkzeuge wie den Grafana-Stack, den OpenAPI Generator und Docker in der Praxis auszuprobieren und dabei so viel wie m\u00f6glich zu lernen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Abgrenzung (Out of Scope):<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit unser Scope nicht zu gro\u00df wird, haben wir den Umfang unserer Beispielanwendung bewusst klein gehalten. Auf eine umfangreiche fachliche Logik haben wir daher ebenso verzichtet wie auf eine komplexe Benutzerverwaltung. Die Anwendung ist schlicht f\u00fcr einen einzelnen Benutzer pro Instanz ausgelegt. Auch ein eigenes Frontend haben wir uns bewusst gespart, da unser Fokus klar auf dem Backend und der dahinterliegenden Infrastruktur lag. Und da es sich um ein Lernprojekt handelt, war auch ein produktiver Einsatz der Anwendung f\u00fcr uns nie das Ziel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit lag der Schwerpunkt des Projekts bewusst nicht auf der Beispielanwendung selbst, sondern auf der Infrastruktur, dem Observability-Stack und den Praktiken rund um deren Entwicklung und Betrieb.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">III. Anwendung<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Use Case<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Bei der Anwendung haben wir uns an der Funktion <strong>\u201eGespeichert\u201c<\/strong> des Kartendienstes Google Maps orientiert. Konkret geht es darum, Orte, Restaurants oder \u00e4hnliche Ziele in Listen zu verwalten und f\u00fcr die Zukunft zu speichern.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Im Gegensatz zu Google Maps konzentrieren wir uns in unserem Projekt ausschlie\u00dflich auf die Backend-Logik dieses Anwendungsfalls.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daf\u00fcr haben wir eine REST-API mit <strong>Java und Spring Boot<\/strong> entwickelt. F\u00fcr die Persistierung verwenden wir <strong>Spring Data JPA<\/strong> in Kombination mit einer <strong>PostgreSQL-Datenbank<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Besonderheiten der Anwendung liegen jedoch weniger in ihrem fachlichen Funktionsumfang als vielmehr in ihrer Architektur sowie in der Definition und Generierung ihrer Schnittstellen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Hexagonale Architektur<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Eine f\u00fcr uns besondere Entscheidung war, das Projekt nach dem Paradigma der <strong>hexagonalen Architektur<\/strong> zu strukturieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Trotz geringer Vorerfahrung haben wir uns bewusst daf\u00fcr entschieden, da wir in vorherigen Projekten die Erfahrung gemacht hatten, dass bei klassischen 3-Tier-Architekturen mit Pr\u00e4sentations-, Logik- und Datenschicht die Grenzen zwischen den einzelnen Schichten mit zunehmender Projektgr\u00f6\u00dfe schnell verschwimmen k\u00f6nnen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch die hexagonale Architektur wollten wir diese Komponenten st\u00e4rker voneinander entkoppeln und insbesondere die Richtung der Abh\u00e4ngigkeiten kontrollieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das f\u00fchrt zwar dazu, dass zus\u00e4tzliche Modelle, Interfaces und Mapping-Schritte ben\u00f6tigt werden, hat f\u00fcr uns jedoch den Vorteil, dass \u00c4nderungen an einer \u00e4u\u00dferen Schnittstelle nicht automatisch Auswirkungen auf andere Teile des Systems haben.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c4ndert sich beispielsweise ein REST-Endpunkt, kann die Persistenzschicht davon unabh\u00e4ngig bleiben.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dar\u00fcber hinaus wollten wir uns durch diese Entkopplung die M\u00f6glichkeit offenhalten, einzelne Adapter sp\u00e4ter auszutauschen. So k\u00f6nnte beispielsweise PostgreSQL durch eine andere Persistenztechnologie ersetzt oder anstelle der REST-Schnittstelle eine andere Art der Kommunikation verwendet werden, ohne die zentrale Gesch\u00e4ftslogik grundlegend ver\u00e4ndern zu m\u00fcssen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">OpenAPI als zentrale Schnittstellendefinition<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Trotz der vergleichsweise geringen Gr\u00f6\u00dfe der Anwendung haben wir uns entschieden, die ben\u00f6tigten Endpunkte und Models zentral in einer <strong>OpenAPI-Spezifikation<\/strong> zu definieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch lassen sich die Schnittstellen und ihre Datenmodelle an einer zentralen Stelle festlegen und gleichzeitig dokumentieren. Da die Spezifikation gemeinsam mit dem restlichen Quellcode versioniert wird, sind \u00c4nderungen an der API au\u00dferdem nachvollziehbar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein weiterer Grund f\u00fcr die Nutzung von OpenAPI war die M\u00f6glichkeit, aus der Spezifikation automatisch Quellcode generieren zu lassen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daf\u00fcr verwenden wir den <strong>OpenAPI Generator<\/strong>. Dieser wird aktiv weiterentwickelt, bietet umfangreiche Dokumentation und unterst\u00fctzt zahlreiche Zielsprachen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gerade mit Blick auf die Wiederverwendbarkeit ist dies f\u00fcr uns interessant. Eine OpenAPI-Spezifikation ist grunds\u00e4tzlich unabh\u00e4ngig von der verwendeten Programmiersprache. Aus derselben Definition k\u00f6nnen daher Assets f\u00fcr unterschiedliche Anwendungen generiert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die OpenAPI-Spezifikation wird damit zur <strong>Single Source of Truth<\/strong> f\u00fcr die Kommunikation zwischen verschiedenen Softwarekomponenten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In unserem Projekt existiert aktuell ausschlie\u00dflich das Backend. W\u00fcrde die Anwendung beispielsweise um ein Angular-Frontend erweitert werden, k\u00f6nnten aus derselben Spezifikation passende API-Clients und Models generiert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch kann sichergestellt werden, dass Front- und Backend dieselbe technische Schnittstellendefinition verwenden. Die funktionale Korrektheit der Anwendung wird dadurch allerdings nicht automatisch garantiert und muss weiterhin \u00fcber Tests abgesichert werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Automatisierte Codegenerierung<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr die Ausf\u00fchrung des OpenAPI Generators haben wir uns f\u00fcr eine zentrale L\u00f6sung \u00fcber ein <strong>Makefile<\/strong> entschieden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unser Ziel war es, die Bedienung f\u00fcr alle Entwickler m\u00f6glichst einheitlich zu gestalten. Der Generator wird deshalb aus einem containerisierten Image ausgef\u00fchrt und die dazugeh\u00f6rigen Befehle werden zentral im Makefile definiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch ist insbesondere sichergestellt, dass alle Entwickler dieselbe Version des OpenAPI Generators verwenden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein vereinfachter Ausschnitt zur Generierung der Endpunkte und Models sieht folgenderma\u00dfen aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">generate:\n\t@echo &quot;&gt;&gt;&gt; Running OpenAPI generator...&quot;\n\tdocker run --rm \\\n\t\t$(USER_FLAG) \\\n\t\t-v &quot;$(CURDIR):\/workspace&quot; \\\n\t\t-w \/workspace \\\n\t\t$(OPENAPI_IMAGE) generate \\\n\t\t\t-i \/workspace\/$(SPEC_FILE) \\\n\t\t\t-c \/workspace\/$(CONFIG_FILE) \\\n\t\t\t-o \/workspace\/$(OUTPUT_DIR)\n\t@echo &quot;&quot;\n\t@echo &quot;&gt;&gt;&gt; Done. Generated files written to: $(GENERATED_DIR)&quot;\n\t@echo &quot;&quot;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Im Verlauf der Entwicklung fiel uns dabei jedoch ein Problem auf: Da die generierten Dateien Teil des Repositorys sind, k\u00f6nnte ein Entwickler diese theoretisch manuell ver\u00e4ndern.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In diesem Fall w\u00fcrde der eingecheckte Code nicht mehr der OpenAPI-Spezifikation entsprechen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wir haben uns deshalb entschieden, das Makefile um eine zus\u00e4tzliche \u00dcberpr\u00fcfung zu erweitern. Dabei werden die Dateien erneut aus der Spezifikation generiert und anschlie\u00dfend mit dem eingecheckten Zustand verglichen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">check-generated: generate\n\t@echo &quot;&gt;&gt;&gt; Diffing generated files against committed state...&quot;\n\t@if ! git diff --quiet -- $(GENERATED_DIR); then \\\n\t\techo &quot;&quot;; \\\n\t\techo &quot;  Generated files are out of sync with $(SPEC_FILE)&quot;; \\\n\t\techo &quot;&quot;; \\\n\t\techo &quot;    Either the spec was changed without regenerating,&quot;; \\\n\t\techo &quot;    or generated files were edited manually.&quot;; \\\n\t\techo &quot;&quot;; \\\n\t\techo &quot;    Fix: run &#039;make generate&#039; locally and commit the result.&quot;; \\\n\t\techo &quot;&quot;; \\\n\t\tgit diff --stat -- $(GENERATED_DIR); \\\n\t\techo &quot;&quot;; \\\n\t\texit 1; \\\n\tfi\n\t@echo &quot;  Generated files are in sync with the spec.&quot;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Diese \u00dcberpr\u00fcfung l\u00e4sst sich anschlie\u00dfend einfach in <strong>GitHub Actions<\/strong> integrieren und stellt sicher, dass die eingecheckten generierten Dateien weiterhin mit der OpenAPI-Spezifikation \u00fcbereinstimmen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">IV. Observability<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Ziel des Observability-Stacks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ein weiteres zentrales Ziel unseres Projekts war die Entwicklung eines wiederverwendbaren <strong>Observability-Stacks<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dieser sollte m\u00f6glichst unabh\u00e4ngig von unserer konkreten Anwendung funktionieren und sich dadurch auch in zuk\u00fcnftige containerisierte Projekte integrieren lassen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unter Observability verstehen wir in diesem Zusammenhang insbesondere die Erfassung der drei zentralen Telemetriearten <strong>Metrics, Logs und Traces<\/strong>. Gemeinsam erm\u00f6glichen diese einen Einblick in den Zustand einer Anwendung und helfen dabei Fehler sowie Performance-Probleme nachvollziehen zu k\u00f6nnen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Weitere Informationen zu den verschiedenen Telemetrie-Signalen bietet die <a href=\"https:\/\/opentelemetry.io\/docs\/concepts\/signals\/\">OpenTelemetry-Dokumentation<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Komponenten<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr die Umsetzung haben wir uns f\u00fcr einen vollst\u00e4ndig containerisierten Stack auf Basis von <a href=\"https:\/\/grafana.com\/grafana\/\">Grafana<\/a>, <a href=\"https:\/\/prometheus.io\/\">Prometheus<\/a>, <a href=\"https:\/\/grafana.com\/oss\/loki\/\">Loki<\/a>, <a href=\"https:\/\/grafana.com\/oss\/tempo\/\">Tempo<\/a> und <a href=\"https:\/\/grafana.com\/docs\/alloy\/latest\/\">Grafana Alloy<\/a> entschieden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die einzelnen Komponenten \u00fcbernehmen unterschiedliche Aufgaben:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Prometheus<\/strong> speichert und verarbeitet Metriken.<\/li>\n\n\n\n<li><strong>Loki<\/strong> dient zur zentralen Speicherung von Logs.<\/li>\n\n\n\n<li><strong>Tempo<\/strong> wird f\u00fcr Distributed Tracing verwendet.<\/li>\n\n\n\n<li><strong>Grafana<\/strong> bildet die gemeinsame Oberfl\u00e4che zur Abfrage und Visualisierung der Daten.<\/li>\n\n\n\n<li><strong>Grafana Alloy<\/strong> fungiert als zentrale Schnittstelle zwischen Anwendungen und Observability-Backends.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Anwendungen m\u00fcssen dadurch nicht direkt mit Prometheus, Loki oder Tempo kommunizieren. Stattdessen werden die Telemetriedaten zun\u00e4chst an Alloy \u00fcbertragen und von dort abh\u00e4ngig vom Datentyp an das entsprechende Backend weitergeleitet.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">OpenTelemetry und OTLP<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr die \u00dcbertragung verwenden wir prim\u00e4r <a href=\"https:\/\/opentelemetry.io\/docs\/\">OpenTelemetry<\/a> und das dazugeh\u00f6rige <strong>OpenTelemetry Protocol (OTLP)<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch ist die Instrumentierung der Anwendung nicht unmittelbar an die konkret verwendeten Grafana-Komponenten gekoppelt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unsere Anwendung sendet Metrics, Logs und Traces \u00fcber OTLP an Alloy. Von dort werden die Metriken an Prometheus, die Logs an Loki und die Traces an Tempo weitergeleitet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der Datenfluss l\u00e4sst sich vereinfacht folgenderma\u00dfen darstellen:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"863\" height=\"400\" data-attachment-id=\"29461\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/image-151\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png\" data-orig-size=\"863,400\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;,&quot;alt&quot;:&quot;&quot;}\" data-image-title=\"image\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png\" alt=\"\" class=\"wp-image-29461\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png 863w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2-300x139.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2-768x356.png 768w\" sizes=\"auto, (max-width: 863px) 100vw, 863px\" \/><\/a><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Instrumentierung der Anwendung<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Bei unserer Spring-Boot-Anwendung erfolgt die OpenTelemetry-Integration direkt innerhalb der Anwendung.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Neben automatisch erzeugten Telemetriedaten haben wir eigene anwendungsspezifische Metriken implementiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daf\u00fcr wird jeder HTTP-Request durch einen Filter erfasst. Gemessen werden unter anderem:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>die Anzahl der Requests,<\/li>\n\n\n\n<li>die Anzahl fehlgeschlagener Requests<\/li>\n\n\n\n<li>sowie die Dauer der einzelnen Requests.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Zus\u00e4tzlich werden Attribute wie HTTP-Methode, Route und Statuscode gespeichert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch k\u00f6nnen sp\u00e4ter beispielsweise Fehlerraten oder Antwortzeiten einzelner Endpunkte analysiert werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Wiederverwendbarkeit und Docker-Fallback<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ein wichtiger Aspekt bei der Entwicklung des Stacks war seine Wiederverwendbarkeit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nicht jede Anwendung unterst\u00fctzt OpenTelemetry direkt. Gerade bei bestehenden oder fremden Docker-Containern m\u00f6chten wir au\u00dferdem nicht zwangsl\u00e4ufig \u00c4nderungen an der jeweiligen Anwendung vornehmen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Deshalb unterst\u00fctzt unser Stack zus\u00e4tzlich einen <strong>Docker-basierten Fallback<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Grafana Alloy kann \u00fcber den Docker-Socket laufende Container automatisch erkennen. \u00dcber Docker-Labels kann anschlie\u00dfend festgelegt werden, ob f\u00fcr einen Container Logs gesammelt oder ein vorhandener Metrics-Endpunkt abgefragt werden soll.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Container kann beispielsweise folgenderma\u00dfen f\u00fcr das Erfassen von Metriken konfiguriert werden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">labels:\n  observability.metrics: &quot;true&quot;\n  observability.metrics_port: &quot;8080&quot;\n  observability.metrics_path: &quot;\/metrics&quot;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Auf \u00e4hnliche Weise kann \u00fcber<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">observability.logs: &quot;true&quot;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">die Erfassung der Standardausgabe eines Containers aktiviert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit kann derselbe Observability-Stack sowohl Anwendungen anbinden, die OpenTelemetry nativ unterst\u00fctzen, als auch solche, die lediglich Logs \u00fcber <code class=\"\" data-line=\"\">stdout<\/code> beziehungsweise <code class=\"\" data-line=\"\">stderr<\/code> oder einen Prometheus-kompatiblen Metrics-Endpunkt bereitstellen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Beide Varianten sollten f\u00fcr dieselben Telemetriedaten jedoch nicht gleichzeitig verwendet werden. W\u00fcrden Logs beispielsweise sowohl \u00fcber OpenTelemetry \u00fcbertragen als auch \u00fcber Docker eingesammelt, k\u00f6nnten dieselben Daten doppelt in Loki gespeichert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr selbst entwickelte Anwendungen ist deshalb die direkte OpenTelemetry-Integration unser bevorzugter Weg. Die Docker-Integration dient prim\u00e4r als Fallback f\u00fcr andere Services.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Betrieb des Stacks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Auch der Observability-Stack selbst wird \u00fcberwacht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Alloy fragt regelm\u00e4\u00dfig die Metrics-Endpunkte von Prometheus, Loki, Tempo, Grafana und Alloy ab und schreibt die gewonnenen Daten ebenfalls nach Prometheus.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch k\u00f6nnen nicht nur die angebundenen Anwendungen, sondern auch die Komponenten des Monitoring-Systems selbst beobachtet werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der gesamte Stack wird \u00fcber <strong>Docker Compose<\/strong> gestartet und ist weitestgehend unabh\u00e4ngig von der eigentlichen Anwendung definiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prometheus, Loki und Tempo sind standardm\u00e4\u00dfig nur innerhalb des gemeinsamen Docker-Netzwerks erreichbar. Nach au\u00dfen m\u00fcssen lediglich tats\u00e4chlich ben\u00f6tigte Schnittstellen wie Grafana oder die OTLP-Endpunkte von Alloy ver\u00f6ffentlicht werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Daten der einzelnen Komponenten werden zus\u00e4tzlich \u00fcber Docker-Volumes persistent gespeichert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch diese Architektur haben wir einen Observability-Stack erhalten, der innerhalb des Projekts entwickelt und getestet wurde, jedoch nicht speziell von unserer Anwendung abh\u00e4ngig ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Neue Docker-basierte Projekte k\u00f6nnen an das gemeinsame Netzwerk angebunden werden und anschlie\u00dfend entweder \u00fcber OpenTelemetry oder \u00fcber die Docker-basierte Erkennung ihre Telemetriedaten bereitstellen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit kann der Stack als Grundlage f\u00fcr weitere Projekte wiederverwendet werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">V. Deployment mit GitOps<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Motivation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Neben der Entwicklung und Beobachtung der Anwendung wollten wir uns auch damit besch\u00e4ftigen, wie diese reproduzierbar und m\u00f6glichst automatisiert deployed werden kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daf\u00fcr haben wir uns f\u00fcr einen <strong>GitOps-basierten Ansatz auf Kubernetes<\/strong> entschieden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">GitOps beschreibt ein Vorgehen, bei dem der gew\u00fcnschte Zustand eines Systems deklarativ definiert und versioniert gespeichert wird. Ein im Cluster laufender Controller gleicht diesen gew\u00fcnschten Zustand kontinuierlich mit dem tats\u00e4chlichen Zustand ab und versucht Abweichungen zu korrigieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit folgt der Ansatz den vier von <a href=\"https:\/\/opengitops.dev\/\">OpenGitOps<\/a> definierten Grundprinzipien: deklarative Konfiguration, Versionierung und Unver\u00e4nderlichkeit des gew\u00fcnschten Zustands, automatisches Abrufen der Konfiguration sowie kontinuierliche Reconciliation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Flux als GitOps-Operator<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Als Kubernetes-Operator verwenden wir <a href=\"https:\/\/fluxcd.io\/\">Flux<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Flux l\u00e4uft direkt innerhalb des Kubernetes-Clusters und \u00fcberwacht ein separates Git-Repository, in dem die Deployment-Konfiguration der Anwendung hinterlegt ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit unterscheidet sich dieser Ansatz von einer klassischen CI\/CD-Pipeline, bei der beispielsweise GitHub Actions nach einem erfolgreichen Build direkt mittels <code class=\"\" data-line=\"\">kubectl<\/code> oder <code class=\"\" data-line=\"\">helm upgrade<\/code> \u00c4nderungen am Cluster durchf\u00fchren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Stattdessen endet die Verantwortung unserer CI zun\u00e4chst mit dem Erstellen und Ver\u00f6ffentlichen der ben\u00f6tigten Artefakte.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der grunds\u00e4tzliche Deployment-Prozess sieht damit folgenderma\u00dfen aus:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"648\" height=\"342\" data-attachment-id=\"29463\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/image-152\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-3.png\" data-orig-size=\"648,342\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;,&quot;alt&quot;:&quot;&quot;}\" data-image-title=\"image\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-3.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-3.png\" alt=\"\" class=\"wp-image-29463\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-3.png 648w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-3-300x158.png 300w\" sizes=\"auto, (max-width: 648px) 100vw, 648px\" \/><\/a><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Continuous Integration und Artefakte<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die Continuous-Integration-Pipeline befindet sich weiterhin im eigentlichen Anwendungsrepository.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bei \u00c4nderungen wird die Anwendung zun\u00e4chst gebaut und getestet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nach einem erfolgreichen Push auf den Main-Branch erzeugt GitHub Actions anschlie\u00dfend ein Multi-Platform-Docker-Image f\u00fcr <code class=\"\" data-line=\"\">linux\/amd64<\/code> und <code class=\"\" data-line=\"\">linux\/arm64<\/code> und ver\u00f6ffentlicht dieses in der <strong>GitHub Container Registry (GHCR)<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Zus\u00e4tzlich wird unser <a href=\"https:\/\/helm.sh\/\">Helm<\/a>-Chart validiert, paketiert und ebenfalls als OCI-Artefakt in GHCR ver\u00f6ffentlicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr beide Artefakte werden Versionen verwendet, die auf den jeweiligen Git-Commit zur\u00fcckgef\u00fchrt werden k\u00f6nnen. Dadurch l\u00e4sst sich eindeutig nachvollziehen, welcher Quellcode einem ver\u00f6ffentlichten Deployment-Artefakt zugrunde liegt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">GitOps-Repository<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Das eigentliche Deployment wird anschlie\u00dfend \u00fcber ein getrenntes <strong>GitOps-Repository<\/strong> gesteuert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Darin wird festgelegt, welche Version des Helm-Charts und welches konkrete Container-Image in einer Umgebung verwendet werden sollen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wir verwenden daf\u00fcr bewusst unver\u00e4nderliche Image-Tags beziehungsweise Digests anstelle eines ver\u00e4nderlichen Tags wie <code class=\"\" data-line=\"\">latest<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch beschreibt ein bestimmter Commit des GitOps-Repositories einen reproduzierbaren Deployment-Zustand und verweist immer auf dieselben Artefakte.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Helm und Flux<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr die Bereitstellung des Helm-Charts verwendet Flux eine <code class=\"\" data-line=\"\">OCIRepository<\/code>-Ressource. Diese verweist auf das in GHCR gespeicherte Chart.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eine <code class=\"\" data-line=\"\">HelmRelease<\/code> beschreibt anschlie\u00dfend deklarativ, mit welcher Version und welchen Konfigurationswerten dieses Chart installiert werden soll.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der <a href=\"https:\/\/fluxcd.io\/flux\/components\/helm\/helmreleases\/\">Flux Helm Controller<\/a> \u00fcbernimmt darauf basierend Installation und Updates des Helm-Releases und pr\u00fcft regelm\u00e4\u00dfig, ob der reale Zustand im Cluster dem in Git definierten Zustand entspricht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit ergibt sich eine klare Trennung zwischen Build und Deployment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">CI:\nSource Code\n   -&gt; Test\n   -&gt; Build\n   -&gt; Docker Image\n   -&gt; Helm Chart\n   -&gt; Registry\n\nGitOps:\nGitOps Repository\n   -&gt; Flux\n   -&gt; Kubernetes<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Eine neue Version der Anwendung wird damit nicht dadurch deployed, dass eine CI-Pipeline direkten Zugriff auf den Kubernetes-Cluster erh\u00e4lt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Stattdessen wird die gew\u00fcnschte Version im GitOps-Repository ge\u00e4ndert. Nachdem diese \u00c4nderung gepr\u00fcft und gemerged wurde, erkennt Flux den neuen gew\u00fcnschten Zustand und setzt die entsprechende \u00c4nderung im Cluster um.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Git wird damit zur <strong>Single Source of Truth f\u00fcr den Deployment-Zustand<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Abh\u00e4ngigkeiten zwischen Komponenten<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Zus\u00e4tzlich verwenden wir Flux-<code class=\"\" data-line=\"\">Kustomization<\/code>-Ressourcen, um verschiedene Teile des Deployments voneinander abh\u00e4ngig zu machen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In unserer Entwicklungsumgebung wird zun\u00e4chst die ben\u00f6tigte Infrastruktur bereitgestellt und erst anschlie\u00dfend die Anwendung deployed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Kustomization der Anwendung besitzt daf\u00fcr eine Abh\u00e4ngigkeit von der Infrastruktur. Flux beginnt mit dem Deployment der Anwendung erst, wenn die Infrastruktur erfolgreich als <code class=\"\" data-line=\"\">Ready<\/code> markiert wurde.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch kann beispielsweise verhindert werden, dass das Backend gestartet wird, bevor die ben\u00f6tigte PostgreSQL-Datenbank bereitsteht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Weitere Informationen zur kontinuierlichen Reconciliation bietet die <a href=\"https:\/\/fluxcd.io\/flux\/concepts\/\">Flux-Dokumentation<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00c4nderungen und Rollbacks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ein weiterer Vorteil des GitOps-Ansatzes zeigt sich bei manuellen Ver\u00e4nderungen innerhalb des Clusters.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wird eine von Flux verwaltete Ressource beispielsweise direkt mittels <code class=\"\" data-line=\"\">kubectl<\/code> ver\u00e4ndert, entspricht der tats\u00e4chliche Zustand nicht mehr dem in Git definierten gew\u00fcnschten Zustand.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Flux kann diese Abweichung erkennen und den definierten Zustand wiederherstellen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Direkte \u00c4nderungen innerhalb des Clusters sollen dadurch zur Ausnahme werden. \u00c4nderungen am Deployment werden stattdessen wie normaler Quellcode \u00fcber Commits und Pull Requests vorgenommen und sind damit nachvollziehbar und reviewbar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dasselbe Prinzip vereinfacht auch Rollbacks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Anstatt manuell rekonstruieren zu m\u00fcssen, welche Konfiguration zuvor aktiv war, kann eine fehlerhafte \u00c4nderung im GitOps-Repository zur\u00fcckgenommen werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Flux erkennt anschlie\u00dfend den ver\u00e4nderten gew\u00fcnschten Zustand und gleicht den Cluster entsprechend mit diesem Zustand ab<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Direkte <code class=\"\" data-line=\"\">helm upgrade<\/code>&#8211; oder <code class=\"\" data-line=\"\">helm rollback<\/code>-Aufrufe sind in unserem Operations-Konzept deshalb lediglich als Notfallmechanismus vorgesehen. Im Normalfall sollen \u00c4nderungen \u00fcber Git erfolgen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Secrets<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Eine Herausforderung bei diesem Ansatz stellen sensible Konfigurationswerte dar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Passw\u00f6rter oder andere Secrets d\u00fcrfen trotz Git als zentraler Quelle nicht im Klartext im Repository gespeichert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr unser Deployment ist deshalb die Verwendung von <a href=\"https:\/\/fluxcd.io\/flux\/guides\/mozilla-sops\/\">SOPS<\/a> zusammen mit <code class=\"\" data-line=\"\">age<\/code> vorgesehen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Secrets k\u00f6nnen damit verschl\u00fcsselt im GitOps-Repository versioniert und erst innerhalb des Clusters von Flux entschl\u00fcsselt werden. Der private Schl\u00fcssel selbst ist dabei nicht Bestandteil des Repositorys.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ergebnis<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Durch diesen Aufbau erreichen wir eine klare Trennung zwischen Anwendung, Build-Prozess und Deployment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das Anwendungsrepository beschreibt, <strong>wie ein Artefakt gebaut wird<\/strong>. Die Container Registry speichert die daraus resultierenden unver\u00e4nderlichen Artefakte. Das GitOps-Repository beschreibt wiederum, <strong>welche dieser Artefakte in einer Umgebung ausgef\u00fchrt werden sollen<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Flux verbindet diese Komponenten, indem es den in Git definierten Zustand kontinuierlich mit dem Kubernetes-Cluster abgleicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dadurch werden Deployments reproduzierbarer, \u00c4nderungen besser nachvollziehbar und m\u00f6glichst wenig Konfiguration existiert ausschlie\u00dflich innerhalb des Clusters.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">VI. Learnings<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">OpenAPI und OpenAPI Generator<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Der API-First-Ansatz mit OpenAPI hat sich f\u00fcr uns als deutlicher Gewinn erwiesen: Da Endpunkte und Modelle zentral in der Spec definiert sind, mussten wir sie nicht doppelt pflegen, und \u00c4nderungen an der Schnittstelle waren sofort f\u00fcr alle Beteiligten nachvollziehbar. Gleichzeitig haben wir gelernt, dass die automatische Generierung allein nicht ausreicht: Ohne den Abgleich zwischen Spec und generierten Dateien (unser check-generated-Target) h\u00e4tten unbemerkte manuelle Anpassungen schnell zu Inkonsistenzen f\u00fchren k\u00f6nnen. Insgesamt hat uns der Ansatz gezeigt, wie viel Zeit und Fehleranf\u00e4lligkeit sich einsparen l\u00e4sst, wenn Schnittstellen als \u201eSingle Source of Truth&#8221; behandelt werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Hexagonale Architektur<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die Entscheidung f\u00fcr eine hexagonale Architektur hat sich trotz anf\u00e4nglich geringer Erfahrung damit ausgezahlt. Der Mehraufwand durch zus\u00e4tzliche Modell-Klassen wurde durch die klare Trennung von Pr\u00e4sentations-, Logik- und Datenschicht ausgeglichen: \u00c4nderungen an einer Schicht wirkten sich nicht ungewollt auf die anderen aus, und ein Austausch einzelner Komponenten wie der Datenbank oder der REST-Schnittstelle w\u00e4re mit deutlich geringerem Aufwand m\u00f6glich als in einer klassischen 3-Tier-Architektur. F\u00fcr uns war das ein guter Beleg daf\u00fcr, dass sich eine h\u00f6here initiale Komplexit\u00e4t langfristig auszahlen kann.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Observability<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Beim Aufbau des Observability-Stacks haben wir gemerkt, wie viel Struktur es bringt, wenn Anwendungen nicht direkt mit den einzelnen Backends kommunizieren, sondern alle Telemetriedaten zun\u00e4chst zentral \u00fcber Grafana Alloy laufen. So bleibt unsere Anwendung unabh\u00e4ngig von den konkreten Backends. \u00c4ndert sich etwas, passen wir nur Alloy an, nicht den Code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Au\u00dferdem haben wir gemerkt, dass Wiederverwendbarkeit nicht hei\u00dft, dass jede Anwendung OpenTelemetry unterst\u00fctzen muss. F\u00fcr eigene Anwendungen ist OpenTelemetry der beste Weg. F\u00fcr fremde oder \u00e4ltere Container gibt es zus\u00e4tzlich einen Docker-basierten Fallback \u00fcber Labels, mit dem Alloy auch Logs \u00fcber stdout oder einen Prometheus-Endpunkt einsammeln kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Noch ein wichtiges Learning: Beide Wege gleichzeitig f\u00fcr dieselben Daten zu nutzen, f\u00fchrt schnell zu doppelten Logs oder Metriken. Deshalb haben wir pro Anwendung bewusst nur einen Weg genutzt. Insgesamt hat uns das gezeigt, dass es bei Observability nicht nur ums Sammeln von Daten geht, sondern genauso um eine klare Datenroute ohne Duplikate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">GitOps und Kubernetes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ein gro\u00dfes Learning f\u00fcr uns war, wie viel angenehmer GitOps das Deployment macht. Die Grundidee: Git ist die einzige Quelle der Wahrheit. Wir beschreiben in Konfigurationsdateien und Helm-Charts, wie unsere Anwendung laufen soll, und der Rest passiert automatisch. GitHub Actions baut bei \u00c4nderungen ein neues Docker-Image und ver\u00f6ffentlicht es in der GitHub Container Registry. Welche Version deployed werden soll, wird anschlie\u00dfend im GitOps-Repository festgelegt. Flux erkennt die dort definierte \u00c4nderung und gleicht den Kubernetes-Cluster mit diesem gew\u00fcnschten Zustand ab. Wir mussten also nie manuell auf den Cluster zugreifen, und jede \u00c4nderung ist \u00fcber Commits nachvollziehbar. Sollte mal was schiefgehen, reicht ein Git-Revert, um zur letzten funktionierenden Version zur\u00fcckzukommen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bei Kubernetes selbst hat uns \u00fcberrascht, wie viel davon eigentlich nur Konfiguration ist. Unsere Anwendung l\u00e4uft in einem Pod, ein Deployment legt fest, wie viele Replicas laufen, und ein Service macht sie im Cluster erreichbar. Besonders hilfreich fanden wir die klare Trennung zwischen Anwendung und Infrastruktur: Unser Backend interessiert sich nicht daf\u00fcr, wo es l\u00e4uft, das regelt die Kubernetes-Konfiguration au\u00dfenrum. Gelernt haben wir auch, Secrets wie Passw\u00f6rter oder JWT-Schl\u00fcssel nie ins Git-Repository zu packen, sondern in Kubernetes-Secrets.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gleichzeitig haben wir gemerkt, dass GitOps auch seine Grenzen hat. Nur weil ein Image gebaut wurde, hei\u00dft das noch lange nicht, dass die Anwendung auch wirklich funktioniert. Tests und Health Checks m\u00fcssen also weiterhin Teil der Pipeline sein. Unterm Strich war das f\u00fcr uns der gr\u00f6\u00dfte Unterschied zu klassischem Deployment. Man beschreibt zuerst in Git, wie der Zielzustand aussehen soll, und das System sorgt danach selbstst\u00e4ndig daf\u00fcr, dass dieser Zustand auch eingehalten wird.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">VII. Fazit<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Zusammenfassend konnten wir mit dem Projekt verschiedene Konzepte moderner Softwareentwicklung und des Betriebs von Anwendungen praktisch miteinander verbinden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit der Spring-Boot-Anwendung haben wir zun\u00e4chst einen konkreten Anwendungsfall geschaffen, anhand dessen wir eine hexagonale Architektur und eine zentral \u00fcber OpenAPI definierte Schnittstelle umsetzen konnten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dar\u00fcber hinaus konnten wir einen wiederverwendbaren Observability-Stack auf Basis von OpenTelemetry, Grafana Alloy, Prometheus, Loki, Tempo und Grafana entwickeln und mit unserer Anwendung testen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch die zus\u00e4tzliche Besch\u00e4ftigung mit Kubernetes und GitOps konnten wir au\u00dferdem den gesamten Weg von der Entwicklung \u00fcber den Build und die Ver\u00f6ffentlichung von Artefakten bis zur deklarativen Bereitstellung einer Anwendung betrachten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Besonders wichtig war uns dabei die Wiederverwendbarkeit der entwickelten Konzepte. Sowohl der Observability-Stack als auch Teile der Deployment- und CI-Struktur k\u00f6nnen als Grundlage f\u00fcr zuk\u00fcnftige Projekte dienen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Der Code zu dem Projekt ist unter folgendem Link verf\u00fcgbar:<\/strong><br><a href=\"https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26\">https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26<\/a><br><a href=\"https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops\">https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel [&hellip;]<\/p>\n","protected":false},"author":1332,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"[]","jetpack_post_was_ever_published":false,"_ppma_block_editor_authors":"{\"authors\":[1261,1268,1271],\"author_categories\":{\"1261\":\"1\",\"1268\":\"1\",\"1271\":\"1\"},\"fallback_author_user\":\"1332\",\"ppma_author_box_select\":\"\",\"selected_authors\":[{\"id\":1261,\"display_name\":\"Alexander Quadflieg\",\"is_guest\":0,\"category_id\":\"1\"},{\"id\":1268,\"display_name\":\"Simon Breit\",\"is_guest\":0,\"category_id\":\"1\"},{\"id\":1271,\"display_name\":\"Pia Schweizer\",\"is_guest\":0,\"category_id\":\"1\"}]}"},"categories":[1],"tags":[150,7,232,417,588,418],"ppma_author":[1261,1268,1271],"class_list":["post-29253","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-ci-cd","tag-cloud","tag-cloud-computing","tag-grafana","tag-loki","tag-prometheus"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Alexander Quadflieg\"\/>\n\t<meta name=\"keywords\" content=\"ci\/cd,cloud,cloud-computing,grafana,loki,prometheus\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Computer Science Blog\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart\" \/>\n\t\t<meta property=\"og:description\" content=\"Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png\" \/>\n\t\t<meta property=\"og:image:width\" content=\"863\" \/>\n\t\t<meta property=\"og:image:height\" content=\"400\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-09-13T20:51:55+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-09-13T20:51:57+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#article\",\"name\":\"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart\",\"headline\":\"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton\",\"author\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/author\\\/alexander_quadflieg\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/image-2.png\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#articleImage\",\"width\":863,\"height\":400},\"datePublished\":\"2026-09-13T22:51:55+02:00\",\"dateModified\":\"2026-09-13T22:51:57+02:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#webpage\"},\"articleSection\":\"Allgemein, CI\\\/CD, Cloud, Cloud-Computing, Grafana, Loki, Prometheus, Alexander Quadflieg, Simon Breit, Pia Schweizer\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/category\\\/allgemein\\\/#listItem\",\"name\":\"Allgemein\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/category\\\/allgemein\\\/#listItem\",\"position\":2,\"name\":\"Allgemein\",\"item\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/category\\\/allgemein\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#listItem\",\"name\":\"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#listItem\",\"position\":3,\"name\":\"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/category\\\/allgemein\\\/#listItem\",\"name\":\"Allgemein\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/#organization\",\"name\":\"Computer Science Blog @ HdM Stuttgart\",\"description\":\"on computer science and media topics\",\"url\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/author\\\/alexander_quadflieg\\\/#author\",\"url\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/author\\\/alexander_quadflieg\\\/\",\"name\":\"Alexander Quadflieg\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f8ee390deb1d6c0b69502d66cfa4b45af64c4ebeaf903a55381e812b628641b4?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Alexander Quadflieg\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#webpage\",\"url\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/\",\"name\":\"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart\",\"description\":\"Dieser Beitrag ist im Rahmen der Vorlesung \\u201eSoftware Development for Cloud Computing\\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\\u00fcgbar:https:\\\/\\\/github.com\\\/simonbreit-dev\\\/software-development-cloud-computing26https:\\\/\\\/github.com\\\/simonbreit-dev\\\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\\u00e4ngige Anwendung pl\\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/2026\\\/09\\\/13\\\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/author\\\/alexander_quadflieg\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/index.php\\\/author\\\/alexander_quadflieg\\\/#author\"},\"datePublished\":\"2026-09-13T22:51:55+02:00\",\"dateModified\":\"2026-09-13T22:51:57+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/#website\",\"url\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/\",\"name\":\"Computer Science Blog @ HdM Stuttgart\",\"description\":\"on computer science and media topics\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/blog.mi.hdm-stuttgart.de\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart","description":"Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel","canonical_url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/","robots":"max-image-preview:large","keywords":"ci\/cd,cloud,cloud-computing,grafana,loki,prometheus","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#article","name":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart","headline":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton","author":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/author\/alexander_quadflieg\/#author"},"publisher":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#articleImage","width":863,"height":400},"datePublished":"2026-09-13T22:51:55+02:00","dateModified":"2026-09-13T22:51:57+02:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#webpage"},"isPartOf":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#webpage"},"articleSection":"Allgemein, CI\/CD, Cloud, Cloud-Computing, Grafana, Loki, Prometheus, Alexander Quadflieg, Simon Breit, Pia Schweizer"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/blog.mi.hdm-stuttgart.de#listItem","position":1,"name":"Home","item":"https:\/\/blog.mi.hdm-stuttgart.de","nextItem":{"@type":"ListItem","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/#listItem","name":"Allgemein"}},{"@type":"ListItem","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/#listItem","position":2,"name":"Allgemein","item":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/","nextItem":{"@type":"ListItem","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#listItem","name":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton"},"previousItem":{"@type":"ListItem","@id":"https:\/\/blog.mi.hdm-stuttgart.de#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#listItem","position":3,"name":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton","previousItem":{"@type":"ListItem","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/#listItem","name":"Allgemein"}}]},{"@type":"Organization","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/#organization","name":"Computer Science Blog @ HdM Stuttgart","description":"on computer science and media topics","url":"https:\/\/blog.mi.hdm-stuttgart.de\/"},{"@type":"Person","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/author\/alexander_quadflieg\/#author","url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/author\/alexander_quadflieg\/","name":"Alexander Quadflieg","image":{"@type":"ImageObject","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/f8ee390deb1d6c0b69502d66cfa4b45af64c4ebeaf903a55381e812b628641b4?s=96&d=mm&r=g","width":96,"height":96,"caption":"Alexander Quadflieg"}},{"@type":"WebPage","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#webpage","url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/","name":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart","description":"Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/#website"},"breadcrumb":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/#breadcrumblist"},"author":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/author\/alexander_quadflieg\/#author"},"creator":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/author\/alexander_quadflieg\/#author"},"datePublished":"2026-09-13T22:51:55+02:00","dateModified":"2026-09-13T22:51:57+02:00"},{"@type":"WebSite","@id":"https:\/\/blog.mi.hdm-stuttgart.de\/#website","url":"https:\/\/blog.mi.hdm-stuttgart.de\/","name":"Computer Science Blog @ HdM Stuttgart","description":"on computer science and media topics","inLanguage":"en-US","publisher":{"@id":"https:\/\/blog.mi.hdm-stuttgart.de\/#organization"}}]},"og:locale":"en_US","og:site_name":"Computer Science Blog","og:type":"article","og:title":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart","og:description":"Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel","og:url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/","og:image":"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png","og:image:secure_url":"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png","og:image:width":863,"og:image:height":400,"article:published_time":"2026-09-13T20:51:55+00:00","article:modified_time":"2026-09-13T20:51:57+00:00","twitter:card":"summary","twitter:title":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton | Computer Science Blog @ HdM Stuttgart","twitter:description":"Dieser Beitrag ist im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c entstanden. Das beschriebene Projekt ist auf GitHub verf\u00fcgbar:https:\/\/github.com\/simonbreit-dev\/software-development-cloud-computing26https:\/\/github.com\/simonbreit-dev\/sdfcc-gitops I. Einleitung Wer schon mal versucht hat herauszufinden, warum eine von mehreren verteilten Services abh\u00e4ngige Anwendung pl\u00f6tzlich nicht mehr wie erwartet funktioniert, wei\u00df: Ohne die richtigen Werkzeuge kommt man schnell an seine Grenzen. Unser Ziel","twitter:image":"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/09\/image-2.png"},"aioseo_meta_data":{"post_id":"29253","title":null,"description":null,"keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2026-09-10 19:05:55","updated":"2026-09-13 20:51:57","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/blog.mi.hdm-stuttgart.de\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/\" title=\"Allgemein\">Allgemein<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tLogging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/blog.mi.hdm-stuttgart.de"},{"label":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},{"label":"Logging, Tracing, Metriken: Unser Weg zu einem wiederverwendbaren Projekt-Skeleton","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/09\/13\/logging-tracing-metriken-unser-weg-zu-einem-wiederverwendbaren-projekt-skeleton\/"}],"jetpack-related-posts":[{"id":5120,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/09\/observability-where-do-we-go-from-here\/","url_meta":{"origin":29253,"position":0},"title":"Observability?! \u2013 Where do we go from here?","author":"Alexander Wallrabenstein","date":"9. February 2019","format":false,"excerpt":"The last two years in software development and operations have been characterized by the emerging idea of \u201cobservability\u201d. The need for a novel concept guiding the efforts to control our systems arose from the accelerating paradigm changes driven by the need to scale and cloud native technologies. In contrast, the\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"MEME: I always, always test my code. The I test it again in production.","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/meme-1.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/meme-1.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/meme-1.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":25560,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/08\/07\/high-availability-and-reliability-in-cloud-computing-ensuring-seamless-operation-despite-the-threat-of-black-swan-events\/","url_meta":{"origin":29253,"position":1},"title":"High Availability and Reliability in Cloud Computing: Ensuring Seamless Operation Despite the Threat of Black Swan Events","author":"mk306","date":"7. August 2023","format":false,"excerpt":"Introduction Nowadays cloud computing has become the backbone of many businesses, offering unparalleled flexibility, scalability and cost-effectiveness. According to O\u2019Reilly\u2019s Cloud Adoption report from 2021, more than 90% of organizations rely on the cloud to run their critical applications and services\u00a0[1]. High availability and reliability of cloud computing systems has\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/CrossRegion.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/CrossRegion.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/CrossRegion.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/CrossRegion.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":3057,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2017\/09\/04\/cloud-security-part-1-a-current-market-overview-and-the-concepts-and-technologies-of-the-cloud\/","url_meta":{"origin":29253,"position":2},"title":"Cloud Security \u2013 Part 1: A current market overview and the concepts and technologies of the cloud","author":"Andreas Fliehr","date":"4. September 2017","format":false,"excerpt":"The first of two blog posts, that are dealing with the latest developments in cloud security. This post covers a current market overview of cloud computing and the concepts and technologies used in the cloud.","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/09\/Shared-kernel-vs.-specialised-kernels.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/09\/Shared-kernel-vs.-specialised-kernels.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/09\/Shared-kernel-vs.-specialised-kernels.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/09\/Shared-kernel-vs.-specialised-kernels.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":3084,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2017\/09\/05\/cloud-security-part-2-the-vulnerabilities-and-threats-of-the-cloud-current-scientific-work-on-cloud-security-conclusion-and-outlook\/","url_meta":{"origin":29253,"position":3},"title":"Cloud Security \u2013 Part 2: The vulnerabilities and threats of the cloud, current scientific work on cloud security, conclusion and outlook","author":"Andreas Fliehr","date":"5. September 2017","format":false,"excerpt":"The second of two blog posts about cloud security. This post covers the vulnerabilities and threats of the cloud, the current scientific work on cloud security and a conclusion and an outlook.","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/09\/Structure-of-Nexen.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/09\/Structure-of-Nexen.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/09\/Structure-of-Nexen.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":3767,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/07\/30\/end-user-monitoring-establish-a-basis-to-understand-operate-and-improve-software-systems\/","url_meta":{"origin":29253,"position":4},"title":"End user monitoring \u2013 Establish a basis to understand, operate and improve software systems","author":"Alexander Wallrabenstein","date":"30. July 2018","format":false,"excerpt":"End user monitoring is crucial for operating and managing software systems safely and effectively. Beyond operations, monitoring constitutes a basic requirement to improve services based on facts instead of instincts. Thus, monitoring plays an important role in the lifecycle of every application. But implementing an effective monitoring solution is challenging\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"Typical monitoring stack","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/07\/fig_03_typicalMonitoringStack.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/07\/fig_03_typicalMonitoringStack.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/07\/fig_03_typicalMonitoringStack.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/07\/fig_03_typicalMonitoringStack.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":24051,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/02\/27\/fog-computing-solving-the-limitations-of-cloud-and-edge-computing\/","url_meta":{"origin":29253,"position":5},"title":"Fog Computing: Solving the limitations of Cloud and Edge Computing","author":"Andreas Nicklaus","date":"27. February 2023","format":false,"excerpt":"Fog computing offers a compromise between cloud and edge computing for real-time, scalable data analysis. Ideal for regional applications and IoT. However, authentication and privacy issues must be addressed.","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/edge-computing-diagram-1024x512.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/edge-computing-diagram-1024x512.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/edge-computing-diagram-1024x512.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/08\/edge-computing-diagram-1024x512.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":1261,"user_id":1332,"is_guest":0,"slug":"alexander_quadflieg","display_name":"Alexander Quadflieg","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/f8ee390deb1d6c0b69502d66cfa4b45af64c4ebeaf903a55381e812b628641b4?s=96&d=mm&r=g","author_category":"","user_url":"","last_name":"Quadflieg","first_name":"Alexander","job_title":"","description":""},{"term_id":1268,"user_id":1335,"is_guest":0,"slug":"simon_breit","display_name":"Simon Breit","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/5f8fff166a5baafc03e122f623793bc78efb37d042fc456dccfa88f645edd9b7?s=96&d=mm&r=g","author_category":"","user_url":"","last_name":"Breit","first_name":"Simon","job_title":"","description":""},{"term_id":1271,"user_id":1338,"is_guest":0,"slug":"pia_schweizer","display_name":"Pia Schweizer","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/1a6b638b471d4c52569bdcb24fe6db5759a284dfabc8435ced37cf6ef75588b0?s=96&d=mm&r=g","author_category":"","user_url":"","last_name":"Schweizer","first_name":"Pia","job_title":"","description":""}],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/29253","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/1332"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=29253"}],"version-history":[{"count":53,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/29253\/revisions"}],"predecessor-version":[{"id":29510,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/29253\/revisions\/29510"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=29253"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=29253"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=29253"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=29253"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}