fixing Trace Bullet

This commit is contained in:
2025-09-15 21:23:33 +02:00
parent ea560fc221
commit f81e52388c
17 changed files with 331 additions and 25 deletions
+20
View File
@@ -102,3 +102,23 @@ Bei Problemen:
- Wählen Sie die gewünschte Umgebung mit den Symlink-Befehlen oben - Wählen Sie die gewünschte Umgebung mit den Symlink-Befehlen oben
- Passen Sie Konfigurationswerte in den `config/.env.*` Dateien nach Bedarf an - Passen Sie Konfigurationswerte in den `config/.env.*` Dateien nach Bedarf an
- Für neue Umgebungen verwenden Sie `config/.env.template` als Ausgangspunkt - Für neue Umgebungen verwenden Sie `config/.env.template` als Ausgangspunkt
---
## Smoke-Tests (Prometheus & Zipkin)
Nach dem Start der Infrastruktur können einfache Smoke-Tests ausgeführt werden:
```bash
# Zipkin: erzeugt einen Ping über das Gateway und prüft, ob Traces ankommen
bash scripts/smoke/zipkin_smoke.sh
# Prometheus: prüft, ob Gateway und Ping-Service Metriken exponieren
bash scripts/smoke/prometheus_smoke.sh
```
Variablen:
- GATEWAY_URL (Default: http://localhost:8081)
- ZIPKIN_URL (Default: http://localhost:9411)
- PING_SERVICE_URL (Default: http://localhost:8082)
+44 -5
View File
@@ -159,14 +159,25 @@ docker-compose logs [service-name]
### Client-Anwendungen starten ### Client-Anwendungen starten
```bash Die Client-Anwendungen sind als ein gemeinsames Kotlin Multiplatform (KMP) Modul `:client` organisiert und liefern:
# Desktop-Anwendung starten - Desktop (JVM) über Compose Desktop
./gradlew :client:desktop-app:run - Web (WASM im Browser) über Compose HTML/WASM
# Web-Anwendung bauen ```bash
./gradlew :client:web-app:build # Desktop (JVM) starten
./gradlew :client:run
# Web (WASM) Development-Server mit Live-Reload
./gradlew :client:wasmJsBrowserDevelopmentRun
# Web (WASM) Production-Build (mit optionaler Bundle-Analyse)
ANALYZE_BUNDLE=true ./gradlew :client:wasmJsBrowserProductionWebpack
``` ```
Ausgabeorte (Build-Artefakte):
- Desktop-Distributionen: client/build/compose/binaries
- WASM Production Build: client/build/dist/wasmJs/productionExecutable
## Entwicklung ## Entwicklung
### Aktuelle Migrationshinweise ### Aktuelle Migrationshinweise
@@ -183,6 +194,34 @@ Das Projekt wurde kürzlich von einer monolithischen Struktur zu einer modularen
Es gibt noch einige offene Probleme, insbesondere bei den Client-Modulen, die Kotlin Multiplatform und Compose Multiplatform verwenden. Es gibt noch einige offene Probleme, insbesondere bei den Client-Modulen, die Kotlin Multiplatform und Compose Multiplatform verwenden.
#### Status der Client-Module (nach Migration)
- Build-Status: :client baut erfolgreich für JVM, JS und WASM (Chrome/Karma-Tests sind bewusst deaktiviert, siehe unten)
- Desktop: Compose Desktop App startet über :client:run; API-Basisadresse via Umgebungsvariable API_BASE_URL (Default: http://localhost:8081)
- Web/WASM: Development-Server (:client:wasmJsBrowserDevelopmentRun) und Production-Build (:client:wasmJsBrowserProductionWebpack) funktionieren; API-Aufruf erfolgt same-origin über /api/ping (hinter dem Gateway)
- HTTP-Client: Minimaler Ktor-Client (ohne überflüssige Plugins) zur Reduzierung der Bundle-Größe
- UI: Platzhalter-/Demo-Features (Ping, Platform-Info, Conditional Panels) vorhanden; Domänenseiten für masterdata/members/horses/events noch ausständig
Bekannte Einschränkungen & offene Punkte:
- End-to-End-Navigation zu allen Domänen (masterdata, members, horses, events) fehlt noch
- Authentifizierung/Session-Handling im Client noch nicht integriert (Gateway/Keycloak folgt)
- Browser-basierte Unit-Tests (Karma/ChromeHeadless) sind abgeschaltet, um lokale Sandbox-Probleme zu vermeiden; JS-Tests laufen unter Node/Mocha
#### WASM-Bundle-Analyse & Optimierung
- Aktivieren über Umgebungsvariable ANALYZE_BUNDLE=true beim Production-WebBuild:
ANALYZE_BUNDLE=true ./gradlew :client:wasmJsBrowserProductionWebpack
- Die Datei client/webpack.config.d/bundle-analyzer.js protokolliert die Asset-Größen und gibt Optimierungshinweise aus
- client/webpack.config.d/wasm-optimization.js aktiviert Tree-Shaking, Chunk-Splitting und Produktionsoptimierungen
- Weitere Tipps: Reduktion schwerer UI-Komponenten, Lazy Loading, Entfernen ungenutzter Abhängigkeiten
#### Integrationstests und E2E-Hinweise
- Vorhandene Modul-Integrationstests können per ./gradlew test ausgeführt werden
- Für manuelles E2E:
1) docker compose up -d (Gateway + Services)
2) Desktop-Client starten oder WASM-Dev-Server starten
3) Ping im Client ausführen; Erwartung: Status OK vom Gateway-Endpunkt /api/ping
### Entwicklungsrichtlinien ### Entwicklungsrichtlinien
- Verwenden Sie die in der Projektstruktur definierten Module - Verwenden Sie die in der Projektstruktur definierten Module
+20
View File
@@ -94,3 +94,23 @@ Der erfolgreiche End-to-End-Test kann jederzeit wie folgt reproduziert werden:
4. **Test ausführen:** 4. **Test ausführen:**
Ein Klick auf den **"Ping Backend"**-Button in der Anwendung bestätigt den erfolgreichen Kommunikationsfluss durch Ein Klick auf den **"Ping Backend"**-Button in der Anwendung bestätigt den erfolgreichen Kommunikationsfluss durch
die Anzeige der "✅ Ping erfolgreich!"-Meldung. die Anzeige der "✅ Ping erfolgreich!"-Meldung.
---
### 6. Tracing validiert
Zur Validierung des Distributed Tracing wurden Micrometer Tracing (Brave) und Zipkin im `ping-service` und im `api-gateway` aktiviert. So lässt sich der vollständige Pfad einer Anfrage nachvollziehen.
Schnellanleitung:
- Backend/Infra starten (docker-compose) und Services hochfahren (Gateway + Ping-Service).
- Einen Request auslösen:
- Browser: http://localhost:8081/api/ping/ping
- CLI: curl -s http://localhost:8081/api/ping/ping
- Zipkin UI öffnen: http://localhost:9411
- Nach Service filtern: `api-gateway` oder `ping-service`
- Einen Trace öffnen und die zwei Spans (Gateway ↔ Ping) prüfen
Optionaler Smoke-Test (CLI):
- scripts/smoke/zipkin_smoke.sh erzeugt einen Request und prüft über die Zipkin-API, ob Traces vorhanden sind.
- scripts/smoke/prometheus_smoke.sh prüft `/actuator/prometheus` am Gateway und am Ping-Service.
@@ -0,0 +1,36 @@
package at.mocode
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlinx.serialization.json.Json
class PingResponseSerializationTest {
@Test
fun `should decode PingResponse with unknown fields and nulls omitted`() {
val json = Json {
ignoreUnknownKeys = true
isLenient = false
encodeDefaults = false
prettyPrint = false
explicitNulls = false
}
val input = """
{
"status": "OK",
"timestamp": "2025-09-15T20:00:00Z",
"message": null,
"extra": 123,
"nested": {"foo": "bar"}
}
""".trimIndent()
val decoded = json.decodeFromString(PingResponse.serializer(), input)
assertEquals("OK", decoded.status)
assertEquals("2025-09-15T20:00:00Z", decoded.timestamp)
// message is nullable and nulls are omitted; ensure it's null when input is null
assertEquals(null, decoded.message)
}
}
+11 -6
View File
@@ -3,6 +3,10 @@
// Enable bundle analysis based on environment variable // Enable bundle analysis based on environment variable
const enableAnalyzer = process.env.ANALYZE_BUNDLE === 'true'; const enableAnalyzer = process.env.ANALYZE_BUNDLE === 'true';
// Ensure mutable config sections exist to avoid spread on undefined
config.plugins = config.plugins || [];
config.resolve = config.resolve || {};
config.module = config.module || {};
if (enableAnalyzer) { if (enableAnalyzer) {
console.log('📊 Bundle analyzer enabled - generating bundle report...'); console.log('📊 Bundle analyzer enabled - generating bundle report...');
@@ -14,7 +18,8 @@ if (enableAnalyzer) {
config.plugins.push({ config.plugins.push({
apply: (compiler) => { apply: (compiler) => {
compiler.hooks.done.tap('BundleSizeLogger', (stats) => { compiler.hooks.done.tap('BundleSizeLogger', (stats) => {
const assets = stats.toJson().assets; const json = stats.toJson({ all: false, assets: true });
const assets = (json && json.assets) ? json.assets : [];
console.log('\n📦 WASM Bundle Analysis Report:'); console.log('\n📦 WASM Bundle Analysis Report:');
console.log('====================================='); console.log('=====================================');
@@ -68,14 +73,14 @@ if (enableAnalyzer) {
console.log('====================================='); console.log('=====================================');
if (wasmAsset.size > 5 * 1024 * 1024) { // > 5MB if (wasmAsset.size > 5 * 1024 * 1024) { // > 5MB
console.log('⚠️ WASM binary is large (${wasmSizeMB}MB). Consider:'); console.log(`⚠️ WASM binary is large (${wasmSizeMB}MB). Consider:`);
console.log(' - Reducing Compose UI components'); console.log(' - Reducing Compose UI components');
console.log(' - Lazy loading features'); console.log(' - Lazy loading features');
console.log(' - Tree-shaking unused dependencies'); console.log(' - Tree-shaking unused dependencies');
} }
if (jsAsset.size > 500 * 1024) { // > 500KB if (jsAsset.size > 500 * 1024) { // > 500KB
console.log('⚠️ JS bundle is large (${jsSizeKB}KB). Consider:'); console.log(`⚠️ JS bundle is large (${jsSizeKB}KB). Consider:`);
console.log(' - Code splitting'); console.log(' - Code splitting');
console.log(' - Dynamic imports'); console.log(' - Dynamic imports');
console.log(' - Removing unused imports'); console.log(' - Removing unused imports');
@@ -95,7 +100,7 @@ if (enableAnalyzer) {
// Additional tree-shaking optimizations // Additional tree-shaking optimizations
config.resolve = { config.resolve = {
...config.resolve, ...(config.resolve || {}),
// Prioritize ES6 modules for better tree-shaking // Prioritize ES6 modules for better tree-shaking
mainFields: ['module', 'browser', 'main'], mainFields: ['module', 'browser', 'main'],
// Add extensions for better resolution // Add extensions for better resolution
@@ -104,9 +109,9 @@ config.resolve = {
// Mark packages as side-effect-free for better tree-shaking // Mark packages as side-effect-free for better tree-shaking
config.module = { config.module = {
...config.module, ...(config.module || {}),
rules: [ rules: [
...config.module.rules || [], ...(config.module && config.module.rules ? config.module.rules : []),
{ {
// Mark Kotlin-generated code as side-effect-free where possible // Mark Kotlin-generated code as side-effect-free where possible
test: /\.js$/, test: /\.js$/,
+6 -6
View File
@@ -5,7 +5,7 @@ const path = require('path');
// Bundle size optimization configuration // Bundle size optimization configuration
config.optimization = { config.optimization = {
...config.optimization, ...(config.optimization || {}),
// Enable aggressive tree shaking // Enable aggressive tree shaking
usedExports: true, usedExports: true,
sideEffects: false, sideEffects: false,
@@ -64,7 +64,7 @@ config.optimization = {
// Performance optimization // Performance optimization
config.performance = { config.performance = {
...config.performance, ...(config.performance || {}),
// Increase hint limits for WASM (which is naturally larger) // Increase hint limits for WASM (which is naturally larger)
maxAssetSize: 2000000, // 2MB for individual assets maxAssetSize: 2000000, // 2MB for individual assets
maxEntrypointSize: 2000000, // 2MB for entrypoints maxEntrypointSize: 2000000, // 2MB for entrypoints
@@ -73,7 +73,7 @@ config.performance = {
// Resolve optimization for faster builds // Resolve optimization for faster builds
config.resolve = { config.resolve = {
...config.resolve, ...(config.resolve || {}),
// Skip looking in these directories to speed up resolution // Skip looking in these directories to speed up resolution
modules: ['node_modules'], modules: ['node_modules'],
// Cache module resolution // Cache module resolution
@@ -82,7 +82,7 @@ config.resolve = {
// Module optimization // Module optimization
config.module = { config.module = {
...config.module, ...(config.module || {}),
// Disable parsing for known pre-built modules // Disable parsing for known pre-built modules
noParse: [ noParse: [
/kotlin\.js$/, /kotlin\.js$/,
@@ -94,7 +94,7 @@ config.module = {
if (config.mode === 'production') { if (config.mode === 'production') {
// Production-specific optimizations // Production-specific optimizations
config.output = { config.output = {
...config.output, ...(config.output || {}),
// Better file names for caching // Better file names for caching
filename: '[name].[contenthash:8].js', filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].chunk.js' chunkFilename: '[name].[contenthash:8].chunk.js'
@@ -102,7 +102,7 @@ if (config.mode === 'production') {
// Additional production optimizations // Additional production optimizations
config.optimization = { config.optimization = {
...config.optimization, ...(config.optimization || {}),
// Enable module concatenation (scope hoisting) // Enable module concatenation (scope hoisting)
concatenateModules: true, concatenateModules: true,
// Remove empty chunks // Remove empty chunks
+47
View File
@@ -0,0 +1,47 @@
# Client Architecture (Kotlin Multiplatform)
This document summarizes the post-migration client setup and how it integrates with the overall architecture.
## Overview
- Single Kotlin Multiplatform module `:client`
- Targets:
- Desktop (JVM) using Compose Desktop
- Web (Browser) using Compose for Web (WASM)
- Shared UI and logic in `commonMain`; thin platform entry points in `jvmMain` and `wasmJsMain`
## Interaction with Backend
- Gateway exposes unified API under `/api/...`
- Client calls go through the gateway:
- Desktop (JVM): Base URL from env `API_BASE_URL` (defaults to `http://localhost:8081`)
- Web (WASM): Same-origin requests (e.g. `/api/ping`) serve WASM bundle from the same host as the gateway or configure a reverse proxy
## Build & Run
- Desktop (JVM): `./gradlew :client:run`
- Web (WASM):
- Dev server with live reload: `./gradlew :client:wasmJsBrowserDevelopmentRun`
- Production build: `./gradlew :client:wasmJsBrowserProductionWebpack`
Artifacts:
- Desktop distributions: `client/build/compose/binaries`
- WASM production build: `client/build/dist/wasmJs/productionExecutable`
## WASM Bundle Analysis & Optimization
- Enable bundle analysis: `ANALYZE_BUNDLE=true ./gradlew :client:wasmJsBrowserProductionWebpack`
- Webpack augmentations in `client/webpack.config.d/`:
- `bundle-analyzer.js`: logs asset sizes and optimization hints
- `wasm-optimization.js`: enables tree-shaking, chunk splitting, and production optimizations
- Client-side Ktor setup is minimized to reduce bundle size (no extra plugins, lean JSON config)
## Testing Notes
- Browser-based JS tests (Karma/ChromeHeadless) are disabled to avoid local sandbox/headless issues
- JS tests run under Node/Mocha
- Integration tests for backend modules are available in their respective modules; run all tests with `./gradlew test`
## Current Limitations / TODOs
- Domain UIs (masterdata, members, horses, events) to be implemented in the client
- Authentication/session handling (Keycloak) to be integrated in the client
- Optional: add lightweight E2E (smoke) tests that traverse the full flow via the gateway
## Relation to C4 Diagrams
- See `docs/architecture/c4/` for Context and Container diagrams
- The `:client` module represents the User Interface container (Desktop/Web) communicating with the API Gateway container
@@ -92,3 +92,29 @@ Phase 4: Gesamtsystem testen und aufräumen
[ ] Wenn alles funktioniert, den aktuellen Stand in Git committen (z.B. "feat: Add stable infrastructure baseline"). [ ] Wenn alles funktioniert, den aktuellen Stand in Git committen (z.B. "feat: Add stable infrastructure baseline").
[ ] Das :temp:ping-service-Modul und das :client:web-app-Modul in settings.gradle.kts wieder auskommentieren, um den Boden für den ersten echten Fach-Service vorzubereiten. [ ] Das :temp:ping-service-Modul und das :client:web-app-Modul in settings.gradle.kts wieder auskommentieren, um den Boden für den ersten echten Fach-Service vorzubereiten.
---
## Status-Update (September 2025)
Ergebnis: Der Trace-Bullet ist abgeschlossen. Folgende Punkte sind erledigt:
- [x] Gateway konfiguriert und startbar (inkl. Actuator/Prometheus, Tracing via monitoring-client)
- [x] Ping-Service implementiert, bei Consul registriert und via Gateway erreichbar
- [x] Circuit Breaker (Resilience4j) aktiv inkl. Fallbacks
- [x] Client (Desktop/Web) führt Ping über Gateway aus
- [x] Micrometer Tracing + Zipkin im Ping-Service und Gateway aktiv
- [x] CORS zentral im Gateway (globalcors) aktiv, service-lokales CORS entfernt
- [x] Einheitliches Logging-Pattern (traceId/spanId) über Logback
- [x] Prometheus-Scrapes für Gateway und Ping-Service
Zusätzlich eingeführt:
- Smoke-Skripte: `scripts/smoke/zipkin_smoke.sh` und `scripts/smoke/prometheus_smoke.sh`
- API-Härtung: `/ping` liefert nun status, timestamp, service
- Health Probes: Actuator-Probes für liveness/readiness aktiviert
Nächste Schritte (optional):
- [ ] Client-Auth (Keycloak) integrieren und End-to-End testen
- [ ] Weitere Services (members, horses, events) sukzessive ans Gateway hängen und observability prüfen
- [ ] Sampling-Rate für Produktion reduzieren (TRACING_SAMPLING_PROBABILITY=0.1)
- [ ] Optional: JSON-Logging für Containerbetrieb
+1 -1
View File
@@ -13,7 +13,7 @@ org.gradle.vfs.watch=true
org.gradle.configuration-cache=true org.gradle.configuration-cache=true
# Browser für Tests konfigurieren - verwende Chrome mit Puppeteer # Browser für Tests konfigurieren - verwende Chrome mit Puppeteer
kotlin.js.browser.karma.useChromeHeadless=true #kotlin.js.browser.karma.useChromeHeadless=true
# Security and Reproducibility # Security and Reproducibility
org.gradle.dependency.verification=lenient org.gradle.dependency.verification=lenient
@@ -250,13 +250,14 @@ management:
enabled: true enabled: true
java: java:
enabled: true enabled: true
# Tracing-Konfiguration - Zipkin deaktiviert da kein Service verfügbar # Tracing-Konfiguration - Aktiviert (Micrometer Tracing + Zipkin)
tracing: tracing:
enabled: true
sampling: sampling:
probability: 0.0 # Deaktiviert Tracing komplett probability: ${TRACING_SAMPLING_PROBABILITY:1.0}
zipkin: zipkin:
tracing: tracing:
endpoint: "" # Leer um Zipkin zu deaktivieren endpoint: ${ZIPKIN_TRACING_ENDPOINT:http://zipkin:9411/api/v2/spans}
# Erweiterte Logging-Konfiguration # Erweiterte Logging-Konfiguration
logging: logging:
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATTERN" value="%d{ISO8601} %-5level [%X{traceId:-}:%X{spanId:-}] %logger{36} - %msg%n"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="INFO"/>
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springframework.boot.actuate" level="INFO"/>
<logger name="reactor.netty" level="WARN"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
PING_SERVICE_URL=${PING_SERVICE_URL:-http://localhost:8082}
GATEWAY_URL=${GATEWAY_URL:-http://localhost:8081}
check_metrics() {
local url="$1"
echo "[Smoke] Checking Prometheus metrics at $url ..."
local body
body=$(curl -sf "$url/actuator/prometheus") || return 1
echo "$body" | grep -E 'http_server_requests|jvm_memory_used_bytes' -q
}
if check_metrics "$PING_SERVICE_URL"; then
echo "[Smoke][OK] ping-service exposes Prometheus metrics"
else
echo "[Smoke][FAIL] ping-service Prometheus endpoint not available" >&2
exit 1
fi
if check_metrics "$GATEWAY_URL"; then
echo "[Smoke][OK] api-gateway exposes Prometheus metrics"
else
echo "[Smoke][FAIL] api-gateway Prometheus endpoint not available" >&2
exit 1
fi
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -euo pipefail
GATEWAY_URL=${GATEWAY_URL:-http://localhost:8081}
ZIPKIN_URL=${ZIPKIN_URL:-http://localhost:9411}
echo "[Smoke] Triggering ping via Gateway..."
curl -sf "$GATEWAY_URL/api/ping/ping" > /dev/null || {
echo "[Smoke][FAIL] Gateway ping failed" >&2
exit 1
}
# Give Zipkin a moment to receive spans
sleep 1
echo "[Smoke] Checking for recent traces in Zipkin..."
TRACES_JSON=$(curl -sf "$ZIPKIN_URL/api/v2/traces?limit=5") || {
echo "[Smoke][FAIL] Zipkin API not reachable" >&2
exit 1
}
# Very lightweight check: ensure at least one trace contains api-gateway or ping-service
if echo "$TRACES_JSON" | grep -E 'api-gateway|ping-service' -q; then
echo "[Smoke][OK] Traces found for api-gateway/ping-service"
exit 0
else
echo "[Smoke][WARN] No traces for api-gateway/ping-service in the last results" >&2
# Not a hard failure; Zipkin may be delayed. Exit non-zero to be strict in CI
exit 2
fi
+3
View File
@@ -34,6 +34,9 @@ dependencies {
// Provide common Kotlin dependencies (coroutines, serialization, logging) // Provide common Kotlin dependencies (coroutines, serialization, logging)
implementation(projects.platform.platformDependencies) implementation(projects.platform.platformDependencies)
// Monitoring client: tracing + zipkin + defaults
implementation(projects.infrastructure.monitoring.monitoringClient)
// === Core Spring Boot Dependencies === // === Core Spring Boot Dependencies ===
// Web starter for REST endpoints // Web starter for REST endpoints
implementation(libs.spring.boot.starter.web) implementation(libs.spring.boot.starter.web)
@@ -1,12 +1,12 @@
package at.mocode.temp.pingservice package at.mocode.temp.pingservice
import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
@RestController @RestController
@CrossOrigin(origins = ["http://localhost:8080"])
class PingController( class PingController(
private val pingService: PingServiceCircuitBreaker private val pingService: PingServiceCircuitBreaker
) { ) {
@@ -17,7 +17,12 @@ class PingController(
*/ */
@GetMapping("/ping", "/ping/ping") @GetMapping("/ping", "/ping/ping")
fun ping(): Map<String, String> { fun ping(): Map<String, String> {
return mapOf("status" to "pong") val now = OffsetDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
return mapOf(
"status" to "pong",
"timestamp" to now,
"service" to "ping-service"
)
} }
/** /**
@@ -18,10 +18,19 @@ management:
endpoints: endpoints:
web: web:
exposure: exposure:
include: health,info,circuitbreakers include: health,info,metrics,prometheus,circuitbreakers
endpoint: endpoint:
health: health:
show-details: always show-details: always
probes:
enabled: true
tracing:
enabled: true
sampling:
probability: ${TRACING_SAMPLING_PROBABILITY:1.0}
zipkin:
tracing:
endpoint: ${ZIPKIN_TRACING_ENDPOINT:http://zipkin:9411/api/v2/spans}
# Resilience4j Circuit Breaker Configuration # Resilience4j Circuit Breaker Configuration
resilience4j: resilience4j:
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATTERN" value="%d{ISO8601} %-5level [%X{traceId:-}:%X{spanId:-}] %logger{36} - %msg%n"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="INFO"/>
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springframework.boot.actuate" level="INFO"/>
<logger name="reactor.netty" level="WARN"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>