refactor(infra-monitoring)
refactor(infra-gateway)
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
Zusammengefasst ergibt sich daraus folgender, konkreter Fahrplan:
|
||||
|
||||
1. **Schritt 0: Aufräumen (ca. 1-2 Stunden)**
|
||||
* [ ] Entfernen Sie den auskommentierten Ktor-Code aus der `infrastructure:gateway:build.gradle.kts`.
|
||||
* [ ] Refaktorieren Sie die Test-Route in `GatewayApplicationTests.kt` auf die Kotlin DSL von Spring Cloud Gateway.
|
||||
* [ ] **(Optional)** Führen Sie `value class`es für stark typisierte IDs oder Konfigurationsparameter im `core`-Modul ein.
|
||||
|
||||
2. **Schritt 1: Phase 2 - Den "Ping-Service" bauen**
|
||||
* [ ] Erstellen Sie ein neues Gradle-Modul `:temp:ping-service`.
|
||||
* [ ] Implementieren Sie eine simple Spring Boot Anwendung darin.
|
||||
* [ ] Fügen Sie die Abhängigkeiten zu `spring-boot-starter-web`, `spring-cloud-starter-consul-discovery` und Ihrem `platform:platform-dependencies` hinzu.
|
||||
* [ ] Erstellen Sie einen `RestController` mit einem `GET /ping` Endpunkt, der `mapOf("status" to "pong")` zurückgibt.
|
||||
* [ ] Konfigurieren Sie die `application.yml` des Services, damit er sich bei Consul registriert und einen eindeutigen Namen (`spring.application.name=ping-service`) hat.
|
||||
|
||||
3. **Schritt 2: Phase 3 - Gateway-Route konfigurieren**
|
||||
* [ ] Fügen Sie in der `application.yml` Ihres Gateways eine Route hinzu, die Anfragen von `/api/ping` an den `ping-service` weiterleitet (Load Balanced via `lb://ping-service`).
|
||||
|
||||
4. **Schritt 3: Phase 4 - Gesamtsystem testen**
|
||||
* [ ] Starten Sie Consul, den Gateway und den Ping-Service.
|
||||
* [ ] Rufen Sie die Gateway-URL (z.B. `http://localhost:8080/api/ping`) auf und verifizieren Sie, dass Sie die `{"status": "pong"}`-Antwort erhalten.
|
||||
* [ ] Erstellen Sie den minimalen "Ping"-Button in Ihrer Client-Anwendung und testen Sie den gesamten Weg.
|
||||
|
||||
Wenn Sie diesen Plan abarbeiten, haben Sie nicht nur Ihre Architektur validiert, sondern auch einige Stellen modernisiert und aufgeräumt. Sie sind auf einem exzellenten Weg
|
||||
@@ -1,56 +1,3 @@
|
||||
/*plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
alias(libs.plugins.ktor)
|
||||
alias(libs.plugins.spring.dependencyManagement)
|
||||
application
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("at.mocode.infrastructure.gateway.ApplicationKt")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(platform(libs.spring.boot.dependencies))
|
||||
implementation(projects.platform.platformDependencies)
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
|
||||
implementation(projects.infrastructure.auth.authClient)
|
||||
implementation(projects.infrastructure.monitoring.monitoringClient)
|
||||
|
||||
// --- Ktor Server ---
|
||||
implementation(libs.ktor.server.core)
|
||||
implementation(libs.ktor.server.netty)
|
||||
implementation(libs.ktor.server.contentNegotiation)
|
||||
implementation(libs.ktor.server.serialization.kotlinx.json)
|
||||
implementation(libs.ktor.server.cors)
|
||||
implementation(libs.ktor.server.callLogging)
|
||||
implementation(libs.ktor.server.defaultHeaders)
|
||||
implementation(libs.ktor.server.statusPages)
|
||||
implementation(libs.ktor.server.auth)
|
||||
implementation(libs.ktor.server.authJwt)
|
||||
implementation(libs.ktor.server.rateLimit)
|
||||
implementation(libs.ktor.server.metrics.micrometer)
|
||||
|
||||
// --- OpenAPI & Swagger for Ktor ---
|
||||
implementation(libs.ktor.server.openapi)
|
||||
implementation(libs.ktor.server.swagger)
|
||||
|
||||
// --- Ktor Client (damit der Gateway Anfragen an die Backend-Services weiterleiten kann) ---
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.cio)
|
||||
implementation(libs.ktor.client.contentNegotiation)
|
||||
implementation(libs.ktor.client.serialization.kotlinx.json)
|
||||
|
||||
// --- Monitoring ---
|
||||
implementation(libs.micrometer.prometheus)
|
||||
|
||||
// --- Testing ---
|
||||
testImplementation(projects.platform.platformTesting)
|
||||
testImplementation(libs.ktor.server.tests)
|
||||
}*/
|
||||
|
||||
// Dieses Modul ist das API-Gateway und der einzige öffentliche Einstiegspunkt
|
||||
// für alle externen Anfragen an das Meldestelle-System.
|
||||
plugins {
|
||||
@@ -75,6 +22,8 @@ dependencies {
|
||||
|
||||
// Stellt die Spring Cloud Gateway und Consul Discovery Abhängigkeiten bereit
|
||||
implementation(libs.bundles.spring.cloud.gateway)
|
||||
// Sichert den reaktiven Webserver (Netty) explizit ab, um Test-/Kontext-Probleme zu vermeiden
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
|
||||
// Bindet die wiederverwendbare Logik zur JWT-Validierung ein.
|
||||
implementation(projects.infrastructure.auth.authClient)
|
||||
@@ -85,5 +34,7 @@ dependencies {
|
||||
// Stellt alle Test-Abhängigkeiten gebündelt bereit.
|
||||
testImplementation(projects.platform.platformTesting)
|
||||
testImplementation(libs.bundles.testing.jvm)
|
||||
// Security im Testkontext, um eine permissive Security-Konfiguration bereitstellen zu können
|
||||
testImplementation(libs.spring.boot.starter.security)
|
||||
|
||||
}
|
||||
|
||||
-3
@@ -2,13 +2,10 @@ package at.mocode.infrastructure.gateway
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
class GatewayApplication
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
runApplication<GatewayApplication>(*args)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,20 @@ spring:
|
||||
name: api-gateway
|
||||
cloud:
|
||||
gateway:
|
||||
# HTTP Client-Timeouts für stabile Upstream-Verbindungen
|
||||
httpclient:
|
||||
connect-timeout: 5000 # in Millisekunden
|
||||
response-timeout: 30s
|
||||
# Globales CORS-Setup (kann pro Umgebung überschrieben werden)
|
||||
globalcors:
|
||||
corsConfigurations:
|
||||
'[/**]':
|
||||
allowedOrigins: "*"
|
||||
allowedMethods: "*"
|
||||
allowedHeaders: "*"
|
||||
# Antwort-Header bereinigen (verhindert doppelte CORS-Header)
|
||||
default-filters:
|
||||
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
|
||||
# Aktiviert die automatische Routen-Erstellung basierend auf Consul
|
||||
discovery:
|
||||
locator:
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package at.mocode.infrastructure.gateway
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.test.web.reactive.server.WebTestClient
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.cloud.gateway.route.RouteLocator
|
||||
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder
|
||||
import java.time.Duration
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.springframework.boot.test.context.TestConfiguration
|
||||
|
||||
@SpringBootTest(
|
||||
classes = [GatewayApplication::class],
|
||||
webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||
properties = [
|
||||
// Use a random port and disable discovery/consul for the test
|
||||
"server.port=0",
|
||||
"spring.cloud.discovery.enabled=false",
|
||||
"spring.cloud.consul.enabled=false",
|
||||
"spring.cloud.consul.config.enabled=false",
|
||||
"spring.cloud.consul.discovery.register=false",
|
||||
// Disable security autoconfiguration for tests
|
||||
"spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration",
|
||||
// Force a reactive web application so that Spring Cloud Gateway auto-config activates
|
||||
"spring.main.web-application-type=reactive",
|
||||
// Gateway discovery locator off; we use explicit test routes
|
||||
"spring.cloud.gateway.discovery.locator.enabled=false"
|
||||
]
|
||||
)
|
||||
@AutoConfigureWebTestClient
|
||||
@Import(GatewayApplicationTests.TestRoutes::class, GatewayApplicationTests.InternalHelloController::class, GatewayApplicationTests.TestSecurityConfig::class)
|
||||
class GatewayApplicationTests {
|
||||
|
||||
@Autowired
|
||||
lateinit var client: WebTestClient
|
||||
|
||||
@Autowired
|
||||
lateinit var routeLocator: RouteLocator
|
||||
|
||||
@Test
|
||||
fun contextLoads() {
|
||||
// If the application context fails to load, this test will fail.
|
||||
}
|
||||
|
||||
@Test
|
||||
fun forwardRouteShouldReturnResponseFromInternalController() {
|
||||
client.get()
|
||||
.uri("/hello")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectBody(String::class.java)
|
||||
.isEqualTo("OK")
|
||||
}
|
||||
|
||||
@RestController
|
||||
class InternalHelloController {
|
||||
@GetMapping("/internal/hello")
|
||||
fun hello(): String = "OK"
|
||||
}
|
||||
|
||||
@Configuration
|
||||
class TestRoutes {
|
||||
@Bean
|
||||
fun routeLocator(builder: RouteLocatorBuilder): RouteLocator = builder.routes()
|
||||
.route("test-forward") { r -> r.path("/hello").uri("forward:/internal/hello") }
|
||||
.build()
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
class TestSecurityConfig {
|
||||
@Bean
|
||||
fun springSecurityFilterChain(): org.springframework.security.web.server.SecurityWebFilterChain =
|
||||
org.springframework.security.config.web.server.ServerHttpSecurity
|
||||
.http()
|
||||
.csrf { it.disable() }
|
||||
.authorizeExchange { exchanges -> exchanges.anyExchange().permitAll() }
|
||||
.build()
|
||||
}
|
||||
}
|
||||
+12
-8
@@ -1,18 +1,22 @@
|
||||
package at.mocode.infrastructure.messaging.client
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.kafka.core.ProducerFactory
|
||||
import org.springframework.kafka.core.DefaultKafkaProducerFactory
|
||||
import org.springframework.kafka.core.reactive.ReactiveKafkaProducerTemplate
|
||||
import reactor.kafka.sender.SenderOptions
|
||||
|
||||
@Configuration
|
||||
/**
|
||||
* Reactive Kafka configuration utilities for creating a ReactiveKafkaProducerTemplate.
|
||||
*/
|
||||
class ReactiveKafkaConfig {
|
||||
|
||||
@Bean
|
||||
fun reactiveKafkaProducerTemplate(producerFactory: ProducerFactory<String, Any>): ReactiveKafkaProducerTemplate<String, Any> {
|
||||
// Nutzt die ProducerFactory aus dem messaging-config-Modul
|
||||
val senderOptions = SenderOptions.create<String, Any>(producerFactory.configurationProperties)
|
||||
/**
|
||||
* Create a ReactiveKafkaProducerTemplate using the configuration from the given ProducerFactory.
|
||||
*/
|
||||
fun reactiveKafkaProducerTemplate(
|
||||
producerFactory: DefaultKafkaProducerFactory<String, Any>
|
||||
): ReactiveKafkaProducerTemplate<String, Any> {
|
||||
val props: Map<String, Any> = producerFactory.configurationProperties
|
||||
val senderOptions: SenderOptions<String, Any> = SenderOptions.create(props)
|
||||
return ReactiveKafkaProducerTemplate(senderOptions)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-3
@@ -36,7 +36,7 @@ class KafkaIntegrationTest {
|
||||
val kafkaConfig = KafkaConfig().apply {
|
||||
bootstrapServers = kafkaContainer.bootstrapServers
|
||||
}
|
||||
producerFactory = kafkaConfig.producerFactory() as DefaultKafkaProducerFactory<String, Any>
|
||||
producerFactory = kafkaConfig.producerFactory()
|
||||
|
||||
val reactiveKafkaConfig = ReactiveKafkaConfig()
|
||||
val reactiveTemplate = reactiveKafkaConfig.reactiveKafkaProducerTemplate(producerFactory)
|
||||
@@ -60,9 +60,18 @@ class KafkaIntegrationTest {
|
||||
ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG to StringDeserializer::class.java,
|
||||
ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG to JsonDeserializer::class.java,
|
||||
ConsumerConfig.AUTO_OFFSET_RESET_CONFIG to "earliest",
|
||||
JsonDeserializer.TRUSTED_PACKAGES to "*"
|
||||
JsonDeserializer.TRUSTED_PACKAGES to "*",
|
||||
JsonDeserializer.USE_TYPE_INFO_HEADERS to false,
|
||||
JsonDeserializer.VALUE_DEFAULT_TYPE to TestEvent::class.java.name
|
||||
)
|
||||
val receiverOptions = ReceiverOptions.create<String, TestEvent>(consumerProps).subscription(listOf(testTopic))
|
||||
|
||||
val jsonValueDeserializer = JsonDeserializer(TestEvent::class.java).apply {
|
||||
addTrustedPackages("*")
|
||||
}
|
||||
val receiverOptions = ReceiverOptions.create<String, TestEvent>(consumerProps)
|
||||
.withKeyDeserializer(StringDeserializer())
|
||||
.withValueDeserializer(jsonValueDeserializer)
|
||||
.subscription(listOf(testTopic))
|
||||
|
||||
// Der Mono, der das nächste empfangene Ereignis darstellt
|
||||
val receivedEvent = KafkaReceiver.create(receiverOptions)
|
||||
|
||||
+24
-43
@@ -1,57 +1,38 @@
|
||||
package at.mocode.infrastructure.messaging.config
|
||||
|
||||
import org.apache.kafka.clients.consumer.ConsumerConfig
|
||||
import org.apache.kafka.clients.producer.ProducerConfig
|
||||
import org.apache.kafka.common.serialization.StringDeserializer
|
||||
import org.apache.kafka.common.serialization.StringSerializer
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.kafka.core.DefaultKafkaProducerFactory
|
||||
import org.springframework.kafka.core.KafkaTemplate
|
||||
import org.springframework.kafka.core.ProducerFactory
|
||||
import org.springframework.kafka.support.serializer.JsonDeserializer
|
||||
import org.springframework.kafka.support.serializer.JsonSerializer
|
||||
|
||||
@Configuration
|
||||
/**
|
||||
* Central Kafka producer configuration used across modules.
|
||||
*
|
||||
* This class can be instantiated programmatically (as done in tests) or
|
||||
* registered as a Spring @Configuration with @Bean methods in an application context.
|
||||
*/
|
||||
class KafkaConfig {
|
||||
|
||||
// KORREKTUR: Von lateinit zu einer public var mit Standardwert, um Tests zu ermöglichen
|
||||
@Value($$"${spring.kafka.bootstrap-servers:localhost:9092}")
|
||||
/**
|
||||
* Comma-separated list of host:port pairs used for establishing the initial connection to the Kafka cluster.
|
||||
*/
|
||||
var bootstrapServers: String = "localhost:9092"
|
||||
|
||||
@Value("\${spring.kafka.consumer.group-id:meldestelle-group}")
|
||||
private lateinit var consumerGroupId: String
|
||||
/**
|
||||
* Common producer properties with sensible defaults (String keys, JSON values).
|
||||
*/
|
||||
fun producerConfigs(): Map<String, Any> = mapOf(
|
||||
ProducerConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers,
|
||||
ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG to StringSerializer::class.java,
|
||||
ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to JsonSerializer::class.java,
|
||||
// Avoid adding type info headers; keeps payloads simple and interoperable.
|
||||
JsonSerializer.ADD_TYPE_INFO_HEADERS to false
|
||||
)
|
||||
|
||||
@Bean
|
||||
fun producerFactory(): ProducerFactory<String, Any> {
|
||||
val configProps = mapOf(
|
||||
ProducerConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers,
|
||||
ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG to StringSerializer::class.java,
|
||||
ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to JsonSerializer::class.java,
|
||||
ProducerConfig.ACKS_CONFIG to "all",
|
||||
ProducerConfig.RETRIES_CONFIG to 3,
|
||||
ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG to true,
|
||||
ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION to 1
|
||||
)
|
||||
return DefaultKafkaProducerFactory(configProps)
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun kafkaTemplate(producerFactory: ProducerFactory<String, Any>): KafkaTemplate<String, Any> {
|
||||
return KafkaTemplate(producerFactory)
|
||||
}
|
||||
|
||||
// NEU: Stellt eine zentrale Map mit den Basis-Konfigurationen für alle Consumer bereit.
|
||||
@Bean
|
||||
fun kafkaConsumerConfiguration(): Map<String, Any> {
|
||||
return mapOf(
|
||||
ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers,
|
||||
ConsumerConfig.GROUP_ID_CONFIG to consumerGroupId,
|
||||
ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG to StringDeserializer::class.java,
|
||||
ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG to JsonDeserializer::class.java,
|
||||
ConsumerConfig.AUTO_OFFSET_RESET_CONFIG to "earliest", // Beginne davon am Anfang, wenn kein Offset existiert
|
||||
JsonDeserializer.TRUSTED_PACKAGES to "*" // Erlaube Deserialisierung aller unserer Klassen
|
||||
)
|
||||
}
|
||||
/**
|
||||
* Strongly typed producer factory to avoid unchecked casts in consumers/tests.
|
||||
*/
|
||||
fun producerFactory(): DefaultKafkaProducerFactory<String, Any> =
|
||||
DefaultKafkaProducerFactory(producerConfigs())
|
||||
}
|
||||
|
||||
@@ -3,14 +3,9 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.kotlin.spring)
|
||||
alias(libs.plugins.spring.boot)
|
||||
alias(libs.plugins.spring.dependencyManagement)
|
||||
}
|
||||
|
||||
// Deaktiviert die Erstellung eines ausführbaren Jars für dieses Bibliotheks-Modul.
|
||||
tasks.getByName("bootJar") {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package at.mocode.infrastructure.monitoring.client
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||
import org.springframework.context.annotation.PropertySource
|
||||
|
||||
/**
|
||||
* AutoConfiguration für das Monitoring-Client-Modul.
|
||||
*
|
||||
* Lädt konservative Default-Properties mit niedriger Priorität, die in jeder Anwendung
|
||||
* leicht per application.properties/-yaml überschrieben werden können.
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(name = [
|
||||
"org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration",
|
||||
"io.micrometer.core.instrument.MeterRegistry"
|
||||
])
|
||||
@PropertySource("classpath:monitoring-defaults.properties")
|
||||
class MonitoringClientAutoConfiguration
|
||||
+1
@@ -0,0 +1 @@
|
||||
at.mocode.infrastructure.monitoring.client.MonitoringClientAutoConfiguration
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# ===================================================================
|
||||
# MELDENSTELLE - MONITORING CLIENT DEFAULTS (via AutoConfiguration)
|
||||
# Diese Konfigurationen werden automatisch von jedem Service übernommen,
|
||||
# der das monitoring-client-Modul einbindet. Sie können in der Anwendung
|
||||
# jederzeit überschrieben werden.
|
||||
# ===================================================================
|
||||
|
||||
# --- Spring Boot Actuator ---
|
||||
# Stellt die /actuator Endpunkte bereit (health, info, prometheus)
|
||||
management.endpoints.web.exposure.include=health,info,prometheus
|
||||
|
||||
# --- Micrometer Tracing ---
|
||||
# Aktiviert das Tracing
|
||||
management.tracing.enabled=true
|
||||
# Definiert, dass Traces immer gesammelt werden sollen (1.0 = 100%)
|
||||
management.tracing.sampling.probability=1.0
|
||||
|
||||
# --- Micrometer Observation (für Metriken UND Tracing) ---
|
||||
# Aktiviert die "Beobachtung" von HTTP Server Requests.
|
||||
# Dies erzeugt automatisch Metriken (Timer) UND Traces für eingehende Anfragen.
|
||||
management.observations.http.server.requests.enabled=true
|
||||
|
||||
# Fügt Anwendungs-Informationen zu den Metriken hinzu
|
||||
management.info.env.enabled=true
|
||||
|
||||
# Definiert den Standard-Endpunkt, an den die Traces gesendet werden.
|
||||
management.zipkin.tracing.endpoint=http://zipkin:9411/api/v2/spans
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package at.mocode.infrastructure.monitoring.client
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner
|
||||
|
||||
class MonitoringClientAutoConfigurationTest {
|
||||
|
||||
private val contextRunner = ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MonitoringClientAutoConfiguration::class.java))
|
||||
|
||||
@Test
|
||||
fun `should load monitoring properties correctly into the environment`() {
|
||||
// Arrange
|
||||
val expectedPropertyValue = "true"
|
||||
val propertyKey = "management.observations.http.server.requests.enabled"
|
||||
|
||||
// Act & Assert
|
||||
contextRunner.run { context ->
|
||||
val actualPropertyValue = context.environment.getProperty(propertyKey)
|
||||
assertThat(actualPropertyValue).isEqualTo(expectedPropertyValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package at.mocode.infrastructure.monitoring.client
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
|
||||
// Minimaler Test-Application-Context für Library-Tests.
|
||||
@SpringBootApplication
|
||||
class MonitoringClientTestApplication
|
||||
+2
@@ -2,7 +2,9 @@ package at.mocode.infrastructure.monitoring
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
import zipkin2.server.internal.EnableZipkinServer
|
||||
|
||||
@EnableZipkinServer
|
||||
@SpringBootApplication
|
||||
class MonitoringServerApplication
|
||||
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package at.mocode.infrastructure.monitoring
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
|
||||
// Startet den ApplicationContext mit Webserver auf zufälligem Port und sicherer Testkonfiguration.
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = [
|
||||
"server.port=0",
|
||||
"management.server.port=0",
|
||||
"zipkin.storage.type=mem",
|
||||
"zipkin.self-tracing.enabled=false",
|
||||
"management.tracing.enabled=false",
|
||||
"management.zipkin.tracing.endpoint="
|
||||
]
|
||||
)
|
||||
class MonitoringServerApplicationTest {
|
||||
|
||||
@Test
|
||||
fun `context loads successfully`() {
|
||||
// Test ist bestanden, wenn der Kontext ohne Exception startet.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user