diff --git a/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/ExternalApiHealthIndicator.java b/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/ExternalApiHealthIndicator.java new file mode 100644 index 00000000000..4ec487f30e3 --- /dev/null +++ b/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/ExternalApiHealthIndicator.java @@ -0,0 +1,34 @@ +/* + * Copyright 2014-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.codecentric.boot.admin.sample.health; + +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.HealthIndicator; + +/** + * A sample {@link HealthIndicator} that simulates checking connectivity to an external + * API. In a real application this would perform an actual HTTP call or similar check. + */ +public class ExternalApiHealthIndicator implements HealthIndicator { + + @Override + public Health health() { + // Simulate a reachable external API + return Health.down().withDetail("url", "https://api.example.com").withDetail("responseTime", "42ms").build(); + } + +} diff --git a/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/ExternalServicesHealthContributor.java b/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/ExternalServicesHealthContributor.java new file mode 100644 index 00000000000..83c36266508 --- /dev/null +++ b/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/ExternalServicesHealthContributor.java @@ -0,0 +1,65 @@ +/* + * Copyright 2014-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.codecentric.boot.admin.sample.health; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.stream.Stream; + +import org.springframework.boot.health.contributor.CompositeHealthContributor; +import org.springframework.boot.health.contributor.HealthContributor; +import org.springframework.boot.health.contributor.HealthContributors; + +/** + * A {@link CompositeHealthContributor} that groups related external-dependency health + * checks under a single {@code /actuator/health/externalServices} entry. + * + *
+ * Spring Boot aggregates the individual {@link HealthContributor}s and rolls up the worst + * status to the composite level, so a single degraded dependency is immediately visible + * both in the top-level health summary and in the drill-down view. + * + *
+ * The composite is registered as a bean named {@code externalServices} in
+ * {@link HealthContributorConfig}, which causes Spring Boot Actuator to expose it at
+ * {@code /actuator/health/externalServices}.
+ */
+// tag::composite-health-contributor[]
+public class ExternalServicesHealthContributor implements CompositeHealthContributor {
+
+ private final Map
+ * The bean name {@code externalServices} is used by Spring Boot Actuator as the path
+ * segment, so the composite becomes available at
+ * {@code /actuator/health/externalServices}.
+ */
+@Configuration(proxyBeanMethods = false)
+public class HealthContributorConfig {
+
+ @Bean
+ public ExternalApiHealthIndicator externalApiHealthIndicator() {
+ return new ExternalApiHealthIndicator();
+ }
+
+ @Bean
+ public MessageBrokerHealthIndicator messageBrokerHealthIndicator() {
+ return new MessageBrokerHealthIndicator();
+ }
+
+ // tag::composite-health-contributor-bean[]
+ @Bean
+ public ExternalServicesHealthContributor externalServices(ExternalApiHealthIndicator externalApi,
+ MessageBrokerHealthIndicator messageBroker) {
+ return new ExternalServicesHealthContributor(externalApi, messageBroker);
+ }
+ // end::composite-health-contributor-bean[]
+
+}
diff --git a/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/MessageBrokerHealthIndicator.java b/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/MessageBrokerHealthIndicator.java
new file mode 100644
index 00000000000..62c882555de
--- /dev/null
+++ b/spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/sample/health/MessageBrokerHealthIndicator.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014-2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.codecentric.boot.admin.sample.health;
+
+import org.springframework.boot.health.contributor.Health;
+import org.springframework.boot.health.contributor.HealthIndicator;
+
+/**
+ * A sample {@link HealthIndicator} that simulates checking an internal message broker. In
+ * a real application this would verify queue depth, connection status, etc.
+ */
+public class MessageBrokerHealthIndicator implements HealthIndicator {
+
+ @Override
+ public Health health() {
+ // Simulate a healthy message broker
+ return Health.unknown().withDetail("broker", "in-memory-stub").withDetail("queueDepth", 0).build();
+ }
+
+}
diff --git a/spring-boot-admin-server-ui/src/main/frontend/components/sba-status-badge.vue b/spring-boot-admin-server-ui/src/main/frontend/components/sba-status-badge.vue
index 86d124ace03..ac94bd6f158 100644
--- a/spring-boot-admin-server-ui/src/main/frontend/components/sba-status-badge.vue
+++ b/spring-boot-admin-server-ui/src/main/frontend/components/sba-status-badge.vue
@@ -36,13 +36,13 @@ export default {
@apply bg-gray-200 text-black text-xs inline-flex items-center uppercase rounded overflow-hidden px-3 py-1;
}
.up {
- @apply bg-green-200 text-green-700;
+ @apply bg-status-up-bg text-status-up-text;
}
.down,
.out_of_service {
- @apply bg-red-200 text-red-700;
+ @apply bg-status-down-bg text-status-down-text;
}
.restricted {
- @apply bg-yellow-200 text-yellow-700;
+ @apply bg-status-restricted-bg text-status-restricted-text;
}
diff --git a/spring-boot-admin-server-ui/src/main/frontend/components/sba-status.vue b/spring-boot-admin-server-ui/src/main/frontend/components/sba-status.vue
index 4b48bd272e0..133dc1bd7df 100644
--- a/spring-boot-admin-server-ui/src/main/frontend/components/sba-status.vue
+++ b/spring-boot-admin-server-ui/src/main/frontend/components/sba-status.vue
@@ -71,17 +71,17 @@ export default {
@apply text-gray-500 mx-auto;
}
.application-status__icon--UP {
- color: #48c78e;
+ color: var(--color-status-up);
}
.application-status__icon--RESTRICTED {
- color: #ffe08a;
+ color: var(--color-status-restricted);
}
.application-status__icon--OUT_OF_SERVICE,
.application-status__icon--DOWN {
- color: #f14668;
+ color: var(--color-status-down);
}
.application-status__icon--UNKNOWN,
.application-status__icon--OFFLINE {
- color: #7a7a7a;
+ color: var(--color-status-unknown);
}
diff --git a/spring-boot-admin-server-ui/src/main/frontend/theme.css b/spring-boot-admin-server-ui/src/main/frontend/theme.css
index 23f6e454003..52c8e25ade0 100644
--- a/spring-boot-admin-server-ui/src/main/frontend/theme.css
+++ b/spring-boot-admin-server-ui/src/main/frontend/theme.css
@@ -15,6 +15,7 @@
*/
@import 'tailwindcss';
+
@custom-variant dark (&:where(.dark, .dark *));
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/typography";
@@ -30,4 +31,25 @@
--color-sba-700: var(--main-700);
--color-sba-800: var(--main-800);
--color-sba-900: var(--main-900);
+
+ /* ── Status colour tokens ─────────────────────────────────────────────
+ * Tailwind utilities: text-status-up, bg-status-up-bg, etc.
+ * Single source of truth for UP/DOWN/RESTRICTED/UNKNOWN across all
+ * components (sba-status-badge, sba-status, wallboard, health panel).
+ */
+ --color-status-up: var(--color-green-400);
+ --color-status-up-bg: var(--color-green-200);
+ --color-status-up-text: var(--color-green-700);
+
+ --color-status-down: var(--color-red-400);
+ --color-status-down-bg: var(--color-red-200);
+ --color-status-down-text: var(--color-red-700);
+
+ --color-status-restricted: var(--color-yellow-500);
+ --color-status-restricted-bg: var(--color-yellow-200);
+ --color-status-restricted-text: var(--color-yellow-700);
+
+ --color-status-unknown: var(--color-gray-400);
+ --color-status-unknown-bg: var(--color-gray-200);
+ --color-status-unknown-text: var(--color-gray-700);
}
diff --git a/spring-boot-admin-server-ui/src/main/frontend/views/instances/details/__snapshots__/health-details.spec.ts.snap b/spring-boot-admin-server-ui/src/main/frontend/views/instances/details/__snapshots__/health-details.spec.ts.snap
index 673cf2a8713..716da368beb 100644
--- a/spring-boot-admin-server-ui/src/main/frontend/views/instances/details/__snapshots__/health-details.spec.ts.snap
+++ b/spring-boot-admin-server-ui/src/main/frontend/views/instances/details/__snapshots__/health-details.spec.ts.snap
@@ -4,7 +4,7 @@ exports[`HealthDetails > Health .details > should format object details correctl
+
+
+
+
+
+
+
-