tutorial

Monitoring Thorntail (WildFly Swarm) Applications with Vigilmon

Thorntail packages WildFly subsystems into an uber JAR for Java microservices — but slow startup, Undertow thread exhaustion, and datasource pool drain are silent failures. Here's how to monitor Thorntail health, Undertow threads, WildFly management API, and JVM metrics with Vigilmon.

Thorntail (formerly WildFly Swarm) packages WildFly application server subsystems as Maven dependencies called "fractions" into a self-contained uber JAR. Each fraction brings in a WildFly subsystem — Undertow for HTTP, CDI for dependency injection, datasources for JDBC, mpHealth for MicroProfile Health. While Thorntail reached end-of-life in 2020 (with Red Hat directing users to Quarkus), many production applications still run on Thorntail 2.x and require active monitoring. Vigilmon gives you the external health checks, heartbeats, and alerting needed to run Thorntail services reliably.

What You'll Set Up

  • MicroProfile Health endpoint monitoring
  • Undertow HTTP listener health checks
  • WildFly management API reachability alerts
  • JVM heap and GC pressure monitoring
  • Thorntail startup time alerting
  • Log error rate heartbeat

Prerequisites

  • Thorntail 2.x (WildFly Swarm 2018.5.0 or later)
  • MicroProfile Health fraction included (io.thorntail:microprofile-health in pom.xml)
  • A free Vigilmon account

Why Monitor Thorntail?

Thorntail's WildFly-based architecture carries the same operational complexity as a full WildFly server, packed into a single JAR. Key failure modes include:

  • Slow startup due to WildFly subsystem initialization — a Thorntail process that takes >60 seconds to start is often misconfigured and may never reach a healthy state before a liveness probe fails.
  • Undertow thread exhaustion — Undertow uses IO and worker thread pools. When the worker pool is saturated, new requests queue silently — the server appears alive but responses are delayed indefinitely.
  • WildFly management API down — the management HTTP API on port 9990 is how you deploy, undeploy, and reconfigure a running Thorntail instance. If it's unreachable, you lose operational control without the application itself failing.
  • Datasource pool drain — WildFly datasource connection pools use a configurable wait timeout. Exhausted pools block requests at the JDBC layer while the MicroProfile Health endpoint continues returning UP.
  • CDI deployment failures — CDI injection errors during startup leave the application partially functional, often silently, with some injection points null.

Vigilmon monitors these conditions via HTTP endpoint checks, heartbeats, and log-based alerting.


Key Metrics to Monitor

| Metric | What It Reveals | |---|---| | /health response | Overall application health via MicroProfile Health | | Undertow request count / error count | HTTP-level failure rate | | Undertow worker thread utilization | Thread pool exhaustion | | WildFly management API reachability | Port 9990 down blocking operational control | | Datasource pool connections | Pool exhaustion causing JDBC blocking | | CDI deployment errors in log | CDI startup failures leaving app partially deployed | | JVM heap utilization | Heap >85% before OOM kill | | GC pause duration | Pause >500ms causing latency spikes | | MicroProfile Metrics endpoint | Metrics pipeline availability | | Startup duration | >60 seconds indicating fraction configuration issue |


Step 1: Add the MicroProfile Health Fraction

Add the MicroProfile Health fraction to your pom.xml:

<dependency>
  <groupId>io.thorntail</groupId>
  <artifactId>microprofile-health</artifactId>
</dependency>
<dependency>
  <groupId>io.thorntail</groupId>
  <artifactId>microprofile-metrics</artifactId>
</dependency>

Add a datasource readiness check:

import org.eclipse.microprofile.health.Health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.sql.DataSource;
import java.sql.Connection;

@Health
@ApplicationScoped
public class DataSourceHealthCheck implements HealthCheck {

    @Inject
    DataSource dataSource;

    @Override
    public HealthCheckResponse call() {
        try (Connection c = dataSource.getConnection()) {
            return HealthCheckResponse.named("datasource")
                .up()
                .withData("connected", true)
                .build();
        } catch (Exception e) {
            return HealthCheckResponse.named("datasource")
                .down()
                .withData("error", e.getMessage())
                .build();
        }
    }
}

Build and run:

mvn thorntail:run

The health endpoint is available at http://localhost:8080/health.


Step 2: Add the Health Monitor in Vigilmon

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter: http://<your-server>:8080/health
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Under Response body check, enter: UP.
  7. Click Save.

Thorntail's MicroProfile Health 1.x/2.x implementation returns a JSON body with "outcome":"UP" when all checks pass. If any health check returns DOWN — including the datasource check above — the endpoint returns 503 and Vigilmon alerts you.


Step 3: Monitor the WildFly Management API

Thorntail exposes the WildFly management HTTP API on port 9990 by default. This is your operational control plane — if it goes down, you can't redeploy, modify datasource settings, or read runtime stats.

Add a Vigilmon monitor:

  1. Click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter: http://<your-server>:9990/management
  4. Set Expected HTTP status to 401 (unauthenticated access returns 401, confirming the management API is alive).
  5. Set Check interval to 2 minutes.
  6. Click Save.

A connection refused or 503 on port 9990 means the management API fraction isn't running — triggering an alert to investigate.


Step 4: Monitor Undertow Worker Thread Health with a Heartbeat

Undertow uses worker and IO thread pools. Under high load, the worker pool can be exhausted with all threads blocked on slow downstream dependencies. This isn't visible from the health endpoint. Monitor it indirectly via response time:

Add a synthetic endpoint to your application:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.enterprise.context.ApplicationScoped;

@Path("/ping")
@ApplicationScoped
public class PingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Response ping() {
        return Response.ok("pong").build();
    }
}

Add a Vigilmon monitor for /ping with:

  • Check interval: 1 minute
  • Response time threshold: Alert if response time >5 seconds (indicating worker thread saturation)

In Vigilmon, set an alert under Advanced Settings → Response Time Alert with a 5-second threshold. A delayed /ping response (which does no I/O) indicates the Undertow worker pool is exhausted.


Step 5: Monitor Thorntail Startup Time

Thorntail startup time directly reflects whether WildFly subsystems initialized cleanly. A startup taking >60 seconds often indicates a missing fraction dependency, misconfigured datasource, or class loading issue that will cause intermittent runtime failures.

Create a startup probe script:

#!/bin/bash
# startup-probe.sh — run after launching Thorntail
HEALTH_URL="http://localhost:8080/health"
VIGILMON_HEARTBEAT="https://vigilmon.online/api/heartbeat/YOUR_ID"
TIMEOUT=60
INTERVAL=5

elapsed=0
while [ "$elapsed" -lt "$TIMEOUT" ]; do
  HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_URL")
  if [ "$HTTP_STATUS" = "200" ]; then
    echo "Thorntail ready in ${elapsed}s"
    curl -s "$VIGILMON_HEARTBEAT"
    exit 0
  fi
  sleep "$INTERVAL"
  elapsed=$((elapsed + INTERVAL))
done

echo "Thorntail startup timed out after ${TIMEOUT}s"
exit 1

Call this script in your systemd ExecStartPost or Kubernetes readiness probe. If it doesn't ping Vigilmon within 60 seconds, your startup has a problem.


Step 6: Monitor Log Error Rate

Thorntail logs using JBoss Logging to stdout and optionally to a file. Set up a log-watching heartbeat that fires when the error rate is acceptable:

#!/bin/bash
# log-watchdog.sh — run via cron every minute
LOG_FILE="/var/log/thorntail/server.log"
VIGILMON_HEARTBEAT="https://vigilmon.online/api/heartbeat/YOUR_ID"

# Count ERROR lines in last 60 seconds
ERROR_COUNT=$(awk -v d="$(date -d '1 minute ago' '+%Y-%m-%d %H:%M')" \
  '$0 > d && / ERROR /' "$LOG_FILE" | wc -l)

# Only ping if error count is below threshold
if [ "$ERROR_COUNT" -lt 5 ]; then
  curl -s "$VIGILMON_HEARTBEAT"
fi

Add this to cron:

* * * * * /opt/thorntail/log-watchdog.sh

Create a Vigilmon Heartbeat monitor with a 3-minute expected interval. If errors spike above 5 per minute, the heartbeat stops and Vigilmon alerts you.


Step 7: Monitor MicroProfile Metrics

Thorntail with microprofile-metrics exposes Prometheus-format metrics at /metrics. Add a Vigilmon monitor to verify the endpoint is reachable:

  1. Click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter: http://<your-server>:8080/metrics
  4. Set Expected HTTP status to 200.
  5. Click Save.

Key Thorntail MicroProfile Metrics to watch in your Prometheus/Alertmanager pipeline:

# Application-specific metric drift
- alert: ThorntailMetricDrift
  expr: rate(application_requests_total[5m]) < 0.1
  for: 10m
  annotations:
    summary: "Thorntail request rate has dropped significantly"

Step 8: Configure Alert Notifications

In Vigilmon, go to Settings → Notifications:

| Monitor | Alert Condition | Severity | |---|---|---| | /health | Non-200 or body missing UP | Critical | | Synthetic /ping | Non-200 | High | | /ping response time | >5 seconds | High | | Management API port 9990 | Non-401 and non-200 | High | | Startup heartbeat | Missed (startup timeout) | Critical | | Log error rate heartbeat | Missed for >3 minutes | Medium | | /metrics endpoint | Non-200 | Medium |


Step 9: Test Your Monitoring Setup

Test Health Alert

# Stop your database to trigger the datasource health check failure
sudo systemctl stop postgresql

# /health should return 503 within one health check cycle
# Verify Vigilmon fires the alert
sudo systemctl start postgresql

Test Management API Alert

# Block port 9990 with a firewall rule
sudo iptables -A INPUT -p tcp --dport 9990 -j DROP

# Verify Vigilmon fires the management API alert
sudo iptables -D INPUT -p tcp --dport 9990 -j DROP

Test Worker Thread Alert

Simulate worker pool saturation by hitting the application with slow requests:

# Flood the application with requests that hold threads
for i in $(seq 1 200); do
  curl -s "http://localhost:8080/api/slow-endpoint" &
done

Verify the Vigilmon /ping response time alert fires as worker threads are exhausted.


Migrating from Thorntail to Quarkus

Since Thorntail reached end-of-life in 2020, Red Hat recommends migrating to Quarkus. When you do, your Vigilmon monitoring setup transfers cleanly:

  • The /health/live and /health/ready endpoints in Quarkus serve the same purpose as Thorntail's /health endpoint.
  • MicroProfile Metrics /metrics endpoint is identical.
  • The management API port changes — Quarkus Dev Services replaces WildFly management.
  • Heartbeat patterns and log error rate monitoring transfer unchanged.

Conclusion

Thorntail's WildFly-based architecture is powerful but carries the operational surface area of a full application server in a microservices package. With Vigilmon you get:

  • Health endpoint monitoring catching datasource failures, CDI errors, and deployment issues
  • Management API reachability ensuring operational control is always available
  • Undertow thread pool health via response time alerting on synthetic checks
  • Startup time monitoring catching fraction misconfiguration at deploy time
  • Log error rate alerting surfacing exception spikes invisible to health endpoints

Start with the /health and management API monitors — they cover the majority of Thorntail runtime failures. Add the startup heartbeat for deployment monitoring and the log error rate watchdog for exception detection.

Sign up for Vigilmon — the first monitor is free.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →