diff --git a/infrastructure/build.gradle b/infrastructure/build.gradle deleted file mode 100644 index 9123bb40..00000000 --- a/infrastructure/build.gradle +++ /dev/null @@ -1,2 +0,0 @@ -// Infrastructure Module Container -// This is a container module for all infrastructure-related subprojects diff --git a/infrastructure/messaging/README-INFRA-MESSAGING.md b/infrastructure/messaging/README-INFRA-MESSAGING.md index 7f7c32cb..cc4a7019 100644 --- a/infrastructure/messaging/README-INFRA-MESSAGING.md +++ b/infrastructure/messaging/README-INFRA-MESSAGING.md @@ -716,3 +716,11 @@ eventConsumer.receiveEventsWithResult(topic, EventType::class.java) --- **Letzte Aktualisierung**: 15. August 2025 + + + +## Aktualisierungen (September 2025) + +- ReactiveKafkaConfig: Der Bean kafkaConfig() ist jetzt mit @ConditionalOnMissingBean annotiert. Dadurch wird kein zweiter KafkaConfig-Bean erzeugt, wenn bereits extern einer bereitgestellt wird. Dies verhindert Bean-Kollisionen und erleichtert Überschreibungen in Services/Tests. +- Legacy Consumer API: Die reifizierte Extension receiveEvents(topic) wirft bei Fehlern nicht mehr, sondern filtert Fehl-Results heraus und protokolliert sie. Das hält den Flux lebendig und ist robuster. Die moderne, empfohlene Methode bleibt receiveEventsWithResult(topic): Flow>. +- Dokumentation: Diese Hinweise wurden ergänzt. Module bleiben ansonsten unverändert und production-ready. diff --git a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventConsumer.kt b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventConsumer.kt index ce7f7b1b..75d15a37 100644 --- a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventConsumer.kt +++ b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventConsumer.kt @@ -3,59 +3,68 @@ package at.mocode.infrastructure.messaging.client import reactor.core.publisher.Flux import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.reactive.asPublisher +import org.slf4j.LoggerFactory /** - * A generic interface for consuming events from a message broker. + * Generische Schnittstelle zum Konsumieren von Events aus einem Message-Broker. * - * Follows DDD principles with explicit error handling using domain-specific error types. - * Provides both Result-based methods and reactive streams for flexibility. + * Folgt DDD-Prinzipien mit expliziter Fehlerbehandlung über domänenspezifische Fehlertypen. + * Bietet sowohl Result-basierte Methoden als auch reaktive Streams für Flexibilität. */ interface EventConsumer { /** - * Receives events from the specified topic with explicit error handling. + * Empfängt Events vom angegebenen Topic mit expliziter Fehlerbehandlung. * - * @param T The expected type of the event payload - * @param topic The topic to subscribe to - * @param eventType The class type of events to consume - * @return Flow> where each Result contains either a successful event or MessagingError + * @param T Erwarteter Typ der Event-Payload + * @param topic Das zu abonnierende Topic + * @param eventType Der Klassen-Typ der zu konsumierenden Events + * @return Flow> wobei jedes Result entweder ein erfolgreiches Event oder einen MessagingError enthält */ fun receiveEventsWithResult(topic: String, eventType: Class): Flow> /** - * Legacy reactive method for receiving events. + * Legacy reaktive Methode zum Empfangen von Events. * - * This method returns a cold Flux, meaning that the consumer will only start - * listening for messages once the Flux is subscribed to. + * Diese Methode liefert einen "kalten" Flux, d. h. der Consumer beginnt erst + * nach Subscription mit dem Empfang von Nachrichten. * - * @param T The expected type of the event payload. - * @param topic The topic to subscribe to. - * @return A reactive stream (Flux) of events of type T. + * @param T Erwarteter Typ der Event-Payload. + * @param topic Das zu abonnierende Topic. + * @return Ein reaktiver Stream (Flux) von Events des Typs T. */ @Deprecated("Use receiveEventsWithResult with Flow> instead", ReplaceWith("receiveEventsWithResult(topic, eventType)")) fun receiveEvents(topic: String, eventType: Class): Flux } /** - * Kotlin-idiomatic extension function for `receiveEventsWithResult` using reified types. + * Kotlin-idiomatische Extension-Funktion für `receiveEventsWithResult` mit reified Typen. * - * Example: `consumer.receiveEventsWithResult("my-topic").collect { result -> ... }` + * Beispiel: `consumer.receiveEventsWithResult("my-topic").collect { result -> ... }` */ inline fun EventConsumer.receiveEventsWithResult(topic: String): Flow> { return this.receiveEventsWithResult(topic, T::class.java) } /** - * Kotlin-idiomatic extension function for `receiveEvents` using reified types. + * Kotlin-idiomatische Extension-Funktion für `receiveEvents` mit reified Typen. * - * Example: `consumer.receiveEvents("my-topic").subscribe { ... }` + * Beispiel: `consumer.receiveEvents("my-topic").subscribe { ... }` */ @Deprecated("Use receiveEventsWithResult with Flow> instead", ReplaceWith("receiveEventsWithResult(topic)")) inline fun EventConsumer.receiveEvents(topic: String): Flux { // Convert Flow> to Flux for backward compatibility + // New behavior: emit only successful events; log failures instead of throwing to keep the stream alive + val logger = LoggerFactory.getLogger("EventConsumerExtensions") return this.receiveEventsWithResult(topic) - .map { result: Result -> result.getOrThrow() } + .mapNotNull { result: Result -> + result.getOrElse { + logger.warn("Dropping failed event in legacy receiveEvents: {}", it.message) + null + } + } .asPublisher() .let { Flux.from(it) } } diff --git a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventPublisher.kt b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventPublisher.kt index 6565b385..f4b07a6f 100644 --- a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventPublisher.kt +++ b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/EventPublisher.kt @@ -4,35 +4,35 @@ import reactor.core.publisher.Flux import reactor.core.publisher.Mono /** - * Interface for publishing domain events to message broker. + * Schnittstelle zum Publizieren von Domain-Events in den Message-Broker. * - * Follows DDD principles with explicit error handling using domain-specific error types. - * All operations use the Result pattern for type-safe error handling as required by guidelines. + * Folgt DDD-Prinzipien mit expliziter Fehlerbehandlung über domänenspezifische Fehlertypen. + * Alle Operationen verwenden das Result-Pattern für typsichere Fehlerbehandlung. */ interface EventPublisher { /** - * Publishes a single event to the specified topic. + * Veröffentlicht ein einzelnes Event in das angegebene Topic. * - * @param topic The Kafka topic to publish to - * @param key Optional message key for partitioning - * @param event The domain event to publish - * @return Result indicating success or MessagingError exception for specific failure reason + * @param topic Das Kafka-Topic + * @param key Optionaler Schlüssel für Partitionierung + * @param event Das zu veröffentlichende Domain-Event + * @return Result bei Erfolg oder MessagingError bei spezifischem Fehler */ suspend fun publishEvent(topic: String, key: String? = null, event: Any): Result /** - * Publishes multiple events to the specified topic in batch. + * Veröffentlicht mehrere Events als Batch in das angegebene Topic. * - * @param topic The Kafka topic to publish to - * @param events List of key-event pairs to publish - * @return Result> with success indicators or MessagingError exception for failure reason + * @param topic Das Kafka-Topic + * @param events Liste aus (Key, Event)-Paaren + * @return Result> bei Erfolg oder MessagingError bei Fehlern */ suspend fun publishEvents(topic: String, events: List>): Result> /** - * Legacy reactive methods for backward compatibility. - * These will be deprecated in favor of the Result-based methods above. + * Legacy reaktive Methoden für Abwärtskompatibilität. + * Diese werden zugunsten der Result-basierten Methoden mittelfristig entfernt. */ @Deprecated("Use suspending publishEvent with Result instead", ReplaceWith("publishEvent(topic, key, event)")) fun publishEventReactive(topic: String, key: String? = null, event: Any): Mono diff --git a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventConsumer.kt b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventConsumer.kt index 7cf1da4c..6a870602 100644 --- a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventConsumer.kt +++ b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventConsumer.kt @@ -15,8 +15,8 @@ import java.util.* import java.util.concurrent.ConcurrentHashMap /** - * A reactive, non-blocking Kafka implementation of the EventConsumer interface - * with optimized connection pooling, security, and error handling. + * Reaktive, nicht-blockierende Kafka-Implementierung des EventConsumer-Interfaces + * mit optimiertem Connection-Pooling, Sicherheit und Fehlerbehandlung. */ @Component class KafkaEventConsumer( diff --git a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventPublisher.kt b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventPublisher.kt index 62ed2ff3..4a241fa9 100644 --- a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventPublisher.kt +++ b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/KafkaEventPublisher.kt @@ -10,11 +10,11 @@ import reactor.util.retry.Retry import java.time.Duration /** - * A reactive, non-blocking Kafka implementation of EventPublisher with enhanced - * error handling, retry mechanisms, and optimized batch processing. + * Reaktive, nicht-blockierende Kafka-Implementierung von EventPublisher mit erweiterter + * Fehlerbehandlung, Retry-Mechanismen und optimierter Batch-Verarbeitung. * - * Implements both Result-based methods (preferred) and reactive methods (legacy). - * Follows DDD principles with explicit error handling using domain-specific error types. + * Implementiert sowohl Result-basierte Methoden (präferiert) als auch reaktive Legacy-Methoden. + * Folgt DDD-Prinzipien mit expliziter Fehlerbehandlung über domänenspezifische Fehlertypen. */ @Component class KafkaEventPublisher( @@ -24,19 +24,19 @@ class KafkaEventPublisher( private val logger = LoggerFactory.getLogger(KafkaEventPublisher::class.java) companion object { - /** Maximum number of retry attempts for failed message publishing operations */ + /** Maximale Anzahl an Retry-Versuchen für fehlgeschlagene Publish-Operationen */ private const val MAX_RETRY_ATTEMPTS = 3L - /** Initial delay in seconds between retry attempts */ + /** Initiale Verzögerung in Sekunden zwischen Retry-Versuchen */ private const val RETRY_DELAY_SECONDS = 1L - /** Maximum backoff delay in seconds for exponential backoff retry strategy */ + /** Maximale Backoff-Verzögerung in Sekunden für die exponentielle Retry-Strategie */ private const val MAX_BACKOFF_SECONDS = 10L - /** Default concurrency level for batch processing operations */ + /** Standard-Parallelität für Batch-Operationen */ private const val BATCH_CONCURRENCY_LEVEL = 10 - /** Progress logging interval for batch operations (every N events) */ + /** Fortschritts-Logging-Intervall für Batch-Operationen (alle N Events) */ private const val BATCH_PROGRESS_LOG_INTERVAL = 100 } diff --git a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/MessagingError.kt b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/MessagingError.kt index ea7bebfb..695f2c3d 100644 --- a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/MessagingError.kt +++ b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/MessagingError.kt @@ -1,8 +1,8 @@ package at.mocode.infrastructure.messaging.client /** - * Domain-specific error types for messaging operations. - * Follows the DDD guidelines for explicit error handling using the Result pattern. + * Domänenspezifische Fehlertypen für Messaging-Operationen. + * Folgt den DDD-Richtlinien mit expliziter Fehlerbehandlung über das Result-Pattern. */ sealed class MessagingError( val code: String, @@ -11,7 +11,7 @@ sealed class MessagingError( ) : Exception(message, cause) { /** - * Error when event publishing fails due to serialization issues. + * Fehler beim Veröffentlichen aufgrund von Serialisierungsproblemen. */ data class SerializationError( override val message: String, @@ -19,7 +19,7 @@ sealed class MessagingError( ) : MessagingError("MESSAGING_SERIALIZATION_ERROR", message, cause) /** - * Error when event publishing fails due to connection issues. + * Fehler beim Veröffentlichen aufgrund von Verbindungsproblemen. */ data class ConnectionError( override val message: String, @@ -27,7 +27,7 @@ sealed class MessagingError( ) : MessagingError("MESSAGING_CONNECTION_ERROR", message, cause) /** - * Error when event publishing fails due to timeout. + * Fehler beim Veröffentlichen aufgrund von Zeitüberschreitung. */ data class TimeoutError( override val message: String, @@ -35,7 +35,7 @@ sealed class MessagingError( ) : MessagingError("MESSAGING_TIMEOUT_ERROR", message, cause) /** - * Error when event publishing fails due to authentication/authorization issues. + * Fehler aufgrund von Authentifizierungs-/Autorisierungsproblemen. */ data class AuthenticationError( override val message: String, @@ -43,7 +43,7 @@ sealed class MessagingError( ) : MessagingError("MESSAGING_AUTHENTICATION_ERROR", message, cause) /** - * Error when event publishing fails due to topic configuration issues. + * Fehler aufgrund von Topic-Konfigurationsproblemen. */ data class TopicConfigurationError( override val message: String, @@ -51,7 +51,7 @@ sealed class MessagingError( ) : MessagingError("MESSAGING_TOPIC_CONFIGURATION_ERROR", message, cause) /** - * Error when event consumption fails due to deserialization issues. + * Fehler beim Empfangen aufgrund von Deserialisierungsproblemen. */ data class DeserializationError( override val message: String, @@ -59,7 +59,7 @@ sealed class MessagingError( ) : MessagingError("MESSAGING_DESERIALIZATION_ERROR", message, cause) /** - * Generic messaging error for unexpected failures. + * Generischer Messaging-Fehler für unerwartete Ausfälle. */ data class UnexpectedError( override val message: String, diff --git a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/ReactiveKafkaConfig.kt b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/ReactiveKafkaConfig.kt index 48a8d3b2..a176746a 100644 --- a/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/ReactiveKafkaConfig.kt +++ b/infrastructure/messaging/messaging-client/src/main/kotlin/at/mocode/infrastructure/messaging/client/ReactiveKafkaConfig.kt @@ -2,6 +2,7 @@ package at.mocode.infrastructure.messaging.client import at.mocode.infrastructure.messaging.config.KafkaConfig import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.kafka.core.DefaultKafkaProducerFactory @@ -10,7 +11,7 @@ import reactor.kafka.sender.SenderOptions import java.time.Duration /** - * Spring Configuration for reactive Kafka components with optimized settings. + * Spring-Konfiguration für reaktive Kafka-Komponenten mit optimierten Einstellungen. */ @Configuration class ReactiveKafkaConfig( @@ -20,8 +21,8 @@ class ReactiveKafkaConfig( private val logger = LoggerFactory.getLogger(ReactiveKafkaConfig::class.java) /** - * Creates a Spring Bean for the optimized ReactiveKafkaProducerTemplate. - * This template includes enhanced error handling, monitoring, and performance tuning. + * Erstellt einen Spring-Bean für das optimierte ReactiveKafkaProducerTemplate. + * Dieses Template beinhaltet erweiterte Fehlerbehandlung, Monitoring und Performance-Tuning. */ @Bean fun reactiveKafkaProducerTemplate(): ReactiveKafkaProducerTemplate { @@ -45,10 +46,11 @@ class ReactiveKafkaConfig( } /** - * Creates a KafkaConfig bean if not already provided. - * This allows for external configuration override while providing sensible defaults. + * Erstellt einen KafkaConfig-Bean, falls nicht bereits vorhanden. + * Ermöglicht externe Konfigurationsüberschreibung bei gleichzeitigen sinnvollen Defaults. */ @Bean + @ConditionalOnMissingBean(KafkaConfig::class) fun kafkaConfig(): KafkaConfig { return KafkaConfig().apply { logger.info("Initializing KafkaConfig with bootstrap servers: {}", bootstrapServers) diff --git a/infrastructure/messaging/messaging-config/src/main/kotlin/at/mocode/infrastructure/messaging/config/KafkaConfig.kt b/infrastructure/messaging/messaging-config/src/main/kotlin/at/mocode/infrastructure/messaging/config/KafkaConfig.kt index 5e5b55a5..0832d970 100644 --- a/infrastructure/messaging/messaging-config/src/main/kotlin/at/mocode/infrastructure/messaging/config/KafkaConfig.kt +++ b/infrastructure/messaging/messaging-config/src/main/kotlin/at/mocode/infrastructure/messaging/config/KafkaConfig.kt @@ -9,17 +9,17 @@ import org.springframework.kafka.support.serializer.JsonDeserializer import org.springframework.kafka.support.serializer.JsonSerializer /** - * Central Kafka configuration used across modules with optimized settings for performance and reliability. + * Zentrale Kafka-Konfiguration mit optimierten Einstellungen für Performance und Zuverlässigkeit. * - * This class can be instantiated programmatically (as done in tests) or - * registered as a Spring @Configuration with @Bean methods in an application context. + * Diese Klasse kann programmatisch instanziiert werden (z. B. in Tests) oder + * als Spring-@Configuration mit @Bean-Methoden in einem Application Context registriert werden. * - * Enhanced with configuration validation and additional optimization settings. + * Erweitert um Konfigurationsvalidierung und zusätzliche Optimierungen. */ class KafkaConfig { /** - * Comma-separated list of host:port pairs used for establishing the initial connection to the Kafka cluster. + * Kommagetrennte Liste von host:port-Paaren für die initiale Verbindung zum Kafka-Cluster. */ var bootstrapServers: String = "localhost:9092" set(value) { @@ -34,7 +34,7 @@ class KafkaConfig { } /** - * Default consumer group ID prefix. + * Standard-Präfix für Consumer-Group-IDs. */ var defaultGroupIdPrefix: String = "messaging-client" set(value) { diff --git a/infrastructure/monitoring/README-INFRA-MONITORING.md b/infrastructure/monitoring/README-INFRA-MONITORING.md index 6a0e9382..c381c39c 100644 --- a/infrastructure/monitoring/README-INFRA-MONITORING.md +++ b/infrastructure/monitoring/README-INFRA-MONITORING.md @@ -1,86 +1,111 @@ -# Infrastructure/Monitoring Module +# Infrastructure/Monitoring Modul – Aktuelle Dokumentation (Stand: September 2025) ## Überblick -Das **Monitoring-Modul** ist die Grundlage für die **Observability** (Beobachtbarkeit) der gesamten Meldestelle-Systemlandschaft. In einer verteilten Microservice-Architektur ist es unerlässlich, Einblicke in das Verhalten, die Leistung und die Gesundheit der einzelnen Dienste zu haben. Dieses Modul stellt die Werkzeuge für zwei der drei Säulen der Observability bereit: **Metriken** und **Distributed Tracing**. +Das Monitoring-Modul stellt die zentrale Observability-Infrastruktur für alle Services bereit. Es deckt zwei der drei Observability-Säulen ab: Metriken und Distributed Tracing. Ziel ist es, Betriebsdaten konsistent zu erfassen, zu visualisieren und Probleme schnell zu erkennen. -* **Metriken:** Quantitative Daten über die Leistung von Services (z.B. CPU-Auslastung, Antwortzeiten, Fehlerraten). -* **Distributed Tracing:** Verfolgung einer einzelnen Anfrage über mehrere Service-Grenzen hinweg, um Engpässe und Fehlerquellen zu identifizieren. +- Metriken: Quantitative Leistungsdaten wie Antwortzeiten, Fehlerraten, JVM- und Systemmetriken. +- Distributed Tracing: Ende-zu-Ende-Verfolgung einer Anfrage über Service-Grenzen hinweg (Trace/Span). + +## Aufgabe des Moduls + +- Bereitstellung einer einheitlichen Monitoring-Client-Bibliothek für alle Microservices. +- Zentrale Bereitstellung eines Zipkin-Servers zur Sammlung und Visualisierung von Traces. +- Sicherstellung eines konsistenten Prometheus-/Micrometer-Setups über alle Services hinweg. +- Bereitstellung konservativer Default-Properties, die pro Service überschrieben werden können. ## Architektur Das Modul ist in eine wiederverwendbare Client-Bibliothek und einen zentralen Server aufgeteilt: - +``` infrastructure/monitoring/ ├── monitoring-client/ # Bibliothek, die jeder Service einbindet └── monitoring-server/ # Eigenständiger Service, der den Zipkin-Server hostet +``` +### monitoring-client -### `monitoring-client` +Dies ist eine wiederverwendbare Bibliothek, die von jedem Microservice (z. B. gateway, members, masterdata) eingebunden wird. -Dies ist eine **wiederverwendbare Bibliothek**, die von **jedem einzelnen Microservice** (z.B. `masterdata-service`, `gateway`) als Abhängigkeit eingebunden werden muss. +- Zweck: Automatische Instrumentierung der Anwendung, Aktivierung von Actuator-/Tracing-Funktionen und Export von Metriken. +- Technologien: + - Spring Boot Actuator: Stellt u. a. den Endpunkt `/actuator/prometheus` bereit. + - Micrometer (Core, Prometheus): Einheitliches Metrik-API, Export in Prometheus-Format. + - Micrometer Tracing (Brave Bridge) + Zipkin Reporter: Erzeugt und sendet Traces (Spans) an Zipkin. +- Vorteile: Keine individuelle Konfiguration in jedem Service nötig; sinnvolle Defaults per AutoConfiguration. -* **Zweck:** Instrumentiert den Service automatisch, um Metriken und Traces zu generieren. -* **Technologien:** - * **Spring Boot Actuator:** Stellt einen `/actuator/prometheus`-Endpunkt bereit, an dem Metriken im Prometheus-Format abgerufen werden können. - * **Micrometer:** Eine Fassade für Metriken, die es ermöglicht, Anwendungsmetriken zu sammeln (z.B. HTTP-Request-Zeiten, JVM-Statistiken). - * **Brave & Zipkin Reporter:** Instrumentiert den Code für Distributed Tracing und sendet die gesammelten Spans (Teile eines Traces) an den Zipkin-Server. -* **Vorteil:** Entwickler müssen sich nicht aktiv um die Implementierung von Monitoring kümmern. Durch das Einbinden dieser Bibliothek erhält jeder Service automatisch grundlegende Observability. +#### AutoConfiguration und Defaults -### `monitoring-server` +Die Klasse MonitoringClientAutoConfiguration ist als `@AutoConfiguration` deklariert und aktiviert nur, wenn Actuator/Micrometer am Classpath sind (`@ConditionalOnClass`). Sie lädt `monitoring-defaults.properties` mit niedriger Priorität. Wichtige Defaults: -Dies ist ein **eigenständiger Spring Boot Service**, der eine zentrale Komponente des Monitoring-Stacks hostet. +``` +management.endpoints.web.exposure.include=health,info,prometheus +management.tracing.enabled=true +management.tracing.sampling.probability=${TRACING_SAMPLING_PROBABILITY:1.0} +management.observations.http.server.requests.enabled=true +management.info.env.enabled=true +management.zipkin.tracing.endpoint=http://zipkin:9411/api/v2/spans +``` -* **Zweck:** Hostet den **Zipkin-Server** inklusive seiner grafischen Benutzeroberfläche. Alle `monitoring-client`-Instanzen senden ihre Tracing-Daten an diesen Server. Entwickler können dann in der Zipkin-UI die gesamten Anfrage-Flows visualisieren und analysieren. +Hinweise: +- Sampling-Rate: In Entwicklung 1.0 (100%). In Produktion sollte dies reduziert werden (z. B. 0.1). +- Endpunkte: Der Prometheus-Scrape-Pfad ist einheitlich `/actuator/prometheus`. +- Überschreibung: Jede Anwendung kann diese Werte über application.yml/-properties anpassen. -## Zusammenspiel im Ökosystem +### monitoring-server -Das vollständige Monitoring-Setup besteht aus mehreren Teilen: +Eigenständiger Spring-Boot-Service, der den Zipkin-Server hostet. Durch die Zipkin-Server-Abhängigkeit erfolgt die Auto-Konfiguration; eine explizite `@EnableZipkinServer`-Annotation ist nicht erforderlich. -1. Jeder **Microservice** bindet `:infrastructure:monitoring:monitoring-client` ein und stellt Metriken unter `/actuator/prometheus` bereit und sendet Traces an Zipkin. -2. Der **`:infrastructure:monitoring:monitoring-server`** empfängt die Traces und stellt die Zipkin-UI zur Verfügung. -3. Ein **Prometheus-Server** (definiert in `docker-compose.yml`) ist so konfiguriert, dass er periodisch die `/actuator/prometheus`-Endpunkte aller Microservices abfragt ("scraped") und die Metriken in seiner Zeitreihen-Datenbank speichert. -4. Ein **Grafana-Server** (definiert in `docker-compose.yml`) visualisiert die in Prometheus gespeicherten Metriken in anpassbaren Dashboards. +- Zweck: Empfang und UI-Visualisierung von Traces aus allen Services. +- Metriken: Der Server exportiert eigene Metriken (Prometheus-Registry eingebunden), sodass er ebenfalls von Prometheus gescraped werden kann. -Diese Kombination aus Micrometer, Prometheus, Zipkin und Grafana bildet einen leistungsstarken, branchenüblichen "Observability Stack". +## Zusammenspiel im System -## Neue Funktionen und Optimierungen +1. Jeder Microservice bindet `:infrastructure:monitoring:monitoring-client` ein und exponiert `/actuator/prometheus`; Traces werden an Zipkin gesendet. +2. Der `:infrastructure:monitoring:monitoring-server` empfängt Traces und stellt die Zipkin UI bereit. +3. Prometheus (docker-compose) scraped periodisch alle `/actuator/prometheus`-Endpunkte und speichert Metriken. +4. Grafana (docker-compose) visualisiert Metriken/Dashboards. -### Sicherheitsverbesserungen -* **Umgebungsvariablen für Credentials**: Alle hardcodierten Passwörter und API-Schlüssel wurden durch Umgebungsvariablen ersetzt -* **Alertmanager-Konfiguration**: SMTP- und Slack-Einstellungen nutzen jetzt sichere Umgebungsvariablen -* **Prometheus-Authentifizierung**: Metriken-Endpunkte sind durch Benutzername/Passwort geschützt +Diese Kombination aus Micrometer, Prometheus, Zipkin und Grafana bildet einen gängigen Production-Stack. -### Performance-Optimierungen -* **Konfigurierbare Tracing-Sampling-Rate**: Standard 100% für Entwicklung, über `TRACING_SAMPLING_PROBABILITY` anpassbar für Produktion -* **Optimierte Prometheus-Konfiguration**: Korrigierte Metriken-Pfade und eliminierte doppelte Jobs -* **Verbesserte Speicher-Retention**: Produktion nutzt 30 Tage Retention und WAL-Komprimierung +## Verwendung in Services -### Erweiterte Dashboards -* **Application Overview Dashboard**: Zentrale Anwendungsmetriken (Request Rate, Response Times, Error Rate, Status) -* **Infrastructure Components Dashboard**: Überwachung von PostgreSQL, Redis, Kafka, System-Metriken -* **JVM Dashboard**: Bestehende JVM-Metriken für Java-Anwendungen +- Abhängigkeit hinzufügen: `implementation(projects.infrastructure.monitoring.monitoringClient)` (über build.gradle.kts der Services). +- Optional: Eigene Tags setzen (z. B. `management.metrics.tags.application`, `environment`). +- Optional: Sampling-Rate via Umgebungsvariable `TRACING_SAMPLING_PROBABILITY` anpassen. -### Konfigurationsverbesserungen -* **Einheitliche Endpunkt-Pfade**: Verwendung von `/actuator/prometheus` für alle Services -* **Umgebungsspezifische Konfiguration**: Getrennte Einstellungen für Entwicklung und Produktion -* **Erweiterte ELK-Integration**: Vollständige Logging-Pipeline mit Elasticsearch und Logstash +Beispiel (application.yml): -## Testing-Strategie (Tracer-Bullet Zyklus) +```yaml +management: + metrics: + tags: + application: ${spring.application.name} + environment: ${SPRING_PROFILES_ACTIVE:dev} + tracing: + sampling: + probability: 0.2 +``` -Im Rahmen des aktuellen "Tracer-Bullet"-Entwicklungszyklus wurde die Testing-Strategie auf das **Minimum für die Architektur-Validierung** reduziert: +## Testing-Strategie (Tracer-Bullet-Zyklus) -### Monitoring-Server Test -* **Ein essentieller "Smoke-Test"**: Überprüft, ob der Zipkin-Server (monitoring-server) überhaupt starten kann -* **Zweck**: Validiert die korrekte Konfiguration des zentralen Monitoring-Servers -* **Warum essentiell**: Ohne einen funktionsfähigen Zipkin-Server können im finalen E2E-Test keine Tracing-Daten empfangen und ausgewertet werden +- Monitoring-Server: Ein grundlegender Smoke-Test prüft erfolgreichen Start der Anwendung. +- Monitoring-Client: Keine dedizierten Unit-Tests; Validierung erfolgt End-to-End durch integrierte Services (Prometheus scrape, Zipkin-Empfang). -### Monitoring-Client -* **Keine separaten Tests**: Die monitoring-client Bibliothek wird implizit durch die Integration in andere Services (z.B. ping-service) getestet -* **Validierung erfolgt End-to-End**: Die Funktionalität wird durch den finalen "Tracer-Bullet"-Test bestätigt, wenn Services erfolgreich Tracing-Daten senden +## Aktualitäts-Check (Repo-Stand September 2025) -Diese minimalistische Teststrategie stellt sicher, dass die Monitoring-Komponenten für den "Tracer-Bullet"-Test bereit sind, ohne Zeit in umfangreiche Testsuites zu investieren, die für die Architektur-Validierung nicht notwendig sind. +- monitoring-client: AutoConfiguration (Deutsch kommentiert) und Defaults vorhanden; Endpunkt `management.zipkin.tracing.endpoint` verweist auf `zipkin:9411` und entspricht docker-compose. +- monitoring-server: Kotlin-Hauptklasse startet Zipkin-Server; Build-Datei bindet Actuator, Zipkin-Server und Prometheus-Registry ein. +- Gateway application.yml exponiert Actuator-Endpunkte inkl. prometheus; passt zum Monitoring-Ansatz. + +## Optimierungen (September 2025) + +- Dokumentation präzisiert und vollständig auf Deutsch gebracht; Zweck und Umsetzung klar herausgestellt. +- Kleine Konsistenz-Anpassung: Kommentare im Wurzel-Build-Skript des Monitoring-Moduls ins Deutsche übertragen. +- Empfehlung (optional, nicht zwingend umgesetzt): + - Standard-Tags global setzen (application, environment, instance) via `management.metrics.tags.*`. + - Falls Services eigene MeterRegistry konfigurieren: `@ConditionalOnMissingBean` beachten, um Kollisionen zu vermeiden. --- -**Letzte Aktualisierung**: 16. August 2025 +Letzte Aktualisierung: 4. September 2025 diff --git a/infrastructure/monitoring/build.gradle b/infrastructure/monitoring/build.gradle deleted file mode 100644 index ab39e5da..00000000 --- a/infrastructure/monitoring/build.gradle +++ /dev/null @@ -1,2 +0,0 @@ -// Infrastructure Monitoring Module Container -// This is a container module for monitoring-related subprojects