Skip to content

Commit 9a7cef7

Browse files
author
wlanboy
committed
added new ressources
1 parent e7adf2c commit 9a7cef7

File tree

2 files changed

+102
-145
lines changed

2 files changed

+102
-145
lines changed

src/main/java/com/wlanboy/javahttpclient/client/K8sDiagnosticService.java

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public class K8sDiagnosticService {
2020

2121
private static final Logger logger = LoggerFactory.getLogger(K8sDiagnosticService.class);
2222
private static final String ENVOY_ADMIN_URL = "http://127.0.0.1:15000";
23+
private static final String ISTIO_GROUP = "networking.istio.io";
24+
private static final String ISTIO_VERSION = "v1alpha3";
2325

2426
private final ApiClient apiClient;
2527
private final CustomObjectsApi customObjectsApi;
@@ -28,8 +30,8 @@ public class K8sDiagnosticService {
2830
public K8sDiagnosticService() throws IOException {
2931
this.apiClient = Config.defaultClient();
3032
this.customObjectsApi = new CustomObjectsApi(apiClient);
31-
this.restTemplate = new RestTemplate(); // Für Envoy Admin API Calls
32-
logger.info("K8s ApiClient und Diagnose-Service initialisiert.");
33+
this.restTemplate = new RestTemplate();
34+
logger.info("K8s Diagnostic Service erfolgreich initialisiert.");
3335
}
3436

3537
public Map<String, Object> getContext() {
@@ -47,76 +49,56 @@ public Map<String, Object> getContext() {
4749
return details;
4850
}
4951

50-
/**
51-
* Fragt den lokalen Envoy Proxy nach netzwerkrelevanten Infos
52-
*/
53-
5452
public Map<String, Object> getFullSidecarDetails() {
55-
Map<String, Object> report = new LinkedHashMap<>(); // LinkedHashMap für stabile Reihenfolge im JSON
53+
Map<String, Object> report = new LinkedHashMap<>();
5654

5755
if (!checkIstioSidecar()) {
58-
report.put("error", "Istio Sidecar nicht aktiv. Port 15021 reagiert nicht.");
56+
report.put("error", "Istio Sidecar Proxy ist nicht aktiv (Port 15021 nicht erreichbar).");
5957
return report;
6058
}
6159

6260
try {
63-
// --- SEKTION A: KONFIGURATION & ERREICHBARKEIT ---
61+
// Sektion A: Erreichbarkeit
6462
Map<String, Object> reachability = new HashMap<>();
6563

66-
// Der Config Dump zeigt, was Envoy theoretisch tun sollte
6764
reachability.put("envoyConfig", restTemplate.getForObject(ENVOY_ADMIN_URL + "/config_dump", Map.class));
68-
69-
// Der Cluster-Status zeigt, was Envoy real sieht (inkl. IP-Adressen der Pods)
7065
String clusters = restTemplate.getForObject(ENVOY_ADMIN_URL + "/clusters", String.class);
7166
reachability.put("activeEndpoints", clusters);
7267
reachability.put("summary", summarizeClusters(clusters));
73-
68+
reachability.put("envoyConfig", restTemplate.getForObject(ENVOY_ADMIN_URL + "/config_dump", Map.class));
7469
report.put("reachability", reachability);
7570

76-
// --- SEKTION B: FEHLER & ANOMALIEN ---
71+
// Sektion B: Gesundheit & Fehler
7772
Map<String, Object> health = new HashMap<>();
78-
79-
// 1. Hole alle Statistiken, die auf Fehler hindeuten
8073
String rawStats = restTemplate.getForObject(
8174
ENVOY_ADMIN_URL + "/stats?filter=.*(errors|5xx|timeout|retry|failed|reset|refused|overflow).*",
8275
String.class);
83-
84-
// 2. Filtere nur die Statistiken, die wirklich Fehler zählen (Wert > 0)
8576
Map<String, String> activeErrors = parseErrorStatsOnly(rawStats);
86-
health.put("activeErrorMetrics", activeErrors);
77+
health.put("activeErrorMetrics", parseErrorStatsOnly(rawStats));
8778
health.put("errorCount", activeErrors.size());
88-
8979
report.put("healthDiagnostics", health);
90-
report.put("timestamp", new Date());
9180

81+
report.put("timestamp", new Date());
9282
} catch (Exception e) {
93-
logger.error("Diagnose fehlgeschlagen", e);
94-
report.put("error", "Kritischer Diagnosefehler: " + e.getMessage());
83+
logger.error("Fehler beim Abruf der Envoy-Details: {}", e.getMessage());
84+
report.put("error", "Envoy Admin API Fehler: " + e.getMessage());
9585
}
9686
return report;
9787
}
9888

99-
/**
100-
* Filtert Statistiken: Nimmt nur Zeilen mit Werten > 0 auf,
101-
* um die "Nadel im Heuhaufen" zu finden.
102-
*/
103-
private Map<String, String> parseErrorStatsOnly(String rawStats) {
104-
Map<String, String> errorMap = new TreeMap<>(); // TreeMap sortiert alphabetisch
89+
private Map<String, String> parseErrorStatsOnly(String rawStats) {
90+
Map<String, String> errorMap = new TreeMap<>();
10591
if (rawStats != null) {
10692
rawStats.lines()
10793
.filter(line -> line.contains(":"))
10894
.forEach(line -> {
10995
String[] parts = line.split(":");
110-
String key = parts[0].trim();
111-
String value = parts[1].trim();
96+
String val = parts[1].trim();
11297
try {
113-
// Wir nehmen nur Metriken auf, die einen Wert ungleich 0 haben
114-
if (Long.parseLong(value) > 0) {
115-
errorMap.put(key, value);
98+
if (Long.parseLong(val) > 0) {
99+
errorMap.put(parts[0].trim(), val);
116100
}
117-
} catch (NumberFormatException e) {
118-
// Falls es kein Long ist (z.B. Text-Status), nehmen wir es trotzdem auf
119-
errorMap.put(key, value);
101+
} catch (Exception ignored) {
120102
}
121103
});
122104
}
@@ -148,22 +130,33 @@ private Map<String, Object> getEnvoyDetails() {
148130
@SuppressWarnings("unchecked")
149131
public List<Object> getIstioResources(String namespace, String type) {
150132
try {
151-
String plural = type.toLowerCase().endsWith("s") ? type.toLowerCase() : type.toLowerCase() + "s";
152-
Object result = customObjectsApi.listNamespacedCustomObject(
153-
"networking.istio.io", "v1alpha3", namespace, plural).execute();
154-
155-
return (result instanceof Map) ? (List<Object>) ((Map<String, Object>) result).get("items")
156-
: Collections.emptyList();
133+
// Normalisierung des Typs (z.B. "gateway" -> "gateways")
134+
String plural = type.toLowerCase();
135+
if (!plural.endsWith("s")) {
136+
plural += "s";
137+
}
138+
139+
// Neuer Fluent-API Stil (ab SDK v12)
140+
// Wir übergeben nur die 4 erforderlichen Parameter
141+
Object result = customObjectsApi
142+
.listNamespacedCustomObject(ISTIO_GROUP, ISTIO_VERSION, namespace, plural)
143+
.execute();
144+
145+
if (result instanceof Map) {
146+
Map<String, Object> resultMap = (Map<String, Object>) result;
147+
return (List<Object>) resultMap.get("items");
148+
}
157149
} catch (Exception e) {
158-
logger.error("Fehler beim Abrufen der Istio-Ressourcen ({}): {}", type, e.getMessage());
159-
return Collections.singletonList(Map.of("error", e.getMessage()));
150+
logger.warn("Fehler beim Laden von {} in {}: {}", type, namespace, e.getMessage());
160151
}
161-
}
152+
return Collections.emptyList();
153+
}
162154

163155
private String summarizeClusters(String rawClusters) {
164-
if (rawClusters == null)
165-
return "Keine Daten";
166-
return (long) rawClusters.split("\n").length + " bekannte Upstream-Endpunkte";
156+
if (rawClusters == null || rawClusters.isBlank())
157+
return "Keine Upstream-Daten";
158+
long count = rawClusters.lines().count();
159+
return count + " aktive Upstream-Cluster-Einträge";
167160
}
168161

169162
private Map<String, String> parseStats(String rawStats) {
@@ -189,7 +182,7 @@ private String getCurrentNamespace() {
189182

190183
private boolean checkIstioSidecar() {
191184
try (Socket socket = new Socket()) {
192-
socket.connect(new InetSocketAddress("127.0.0.1", 15021), 150);
185+
socket.connect(new InetSocketAddress("127.0.0.1", 15021), 200);
193186
return true;
194187
} catch (Exception e) {
195188
return false;

0 commit comments

Comments
 (0)