PH Review build. Anything marked PH or [placeholder] needs real data before launch. GitHub buttons point to a placeholder URL.

Replay every failed request

Bugs are inevitable. Lost afternoons aren't.

Debug one Spring Boot app in 5 minutes. No collectors, no log cluster, no observability stack to stand up first.

order-service RequestsIncidentsHealthRabbitMQ Example data
MethodPathStatusTime
GET/api/orders/104220038 ms
POST/api/orders5003.01 s
GET/api/orders?status=open20061 ms
PUT/api/orders/103920444 ms
GET/api/orders/99994049 ms
POST/api/orders201112 ms
GET/api/orders/103820035 ms
500
POST /api/orders
Internal Server Error 3.01 s 14:07:32 UTC
Matched rule 5xx on /api/orders/**
Outgoing calls
OUTGET customer-service /api/customers/8820041 ms
OUTPOST inventory-service /api/inventory/reservetimeout3.00 s
Exception
ResourceAccessException: I/O error on POST request
for "http://inventory-service/api/inventory/reserve":
Read timed out
  at o.s.web.client.RestTemplate.doExecute(RestTemplate.java)
  at c.example.orders.InventoryClient.reserve(InventoryClient.java:57)

The 500 took a second. Finding it took the afternoon.

A customer reports a failed checkout. You know the drill.

Illustrative timeline
  1. Ticket lands"Checkout failed for me." No request ID, no timestamp you can trust.
  2. grep across instancesThousands of lines. Three pods. The one you need rotated out.
  3. Reconstruct the requestGuess the payload. Guess which downstream call failed.
  4. Add logging, redeploy, waitAnd hope it happens again.
With EasyDebug

Open the failed request. The status, the outgoing calls it made and where it broke. One screen.

POST/api/orders5003.01 sOpen

Replay the request that failed.

  1. POST /api/orders lands on order-service.
  2. customer-service answers. 200 in 41 ms.
  3. inventory-service goes quiet. The clock keeps running.
  4. Read timed out. RestTemplate gives up.
  5. The client gets a 500. EasyDebug already has the calls, the timing and the trace.
Trace POST /api/orders Example data
INPOST /api/orders 500
OUTcustomer-service 200
OUTinventory-service timeout
Matched rule 5xx on /api/orders/**
ResourceAccessException: I/O error on POST request
for "http://inventory-service/api/inventory/reserve": Read timed out
  at c.example.orders.InventoryClient.reserve(InventoryClient.java:57)

See the failure. Skip the noise.

Five things, built for the moment something breaks.

One dashboard for every incident

Failed requests, the calls they made and service health, side by side. Start the investigation where the error is.

Open incidentsExample data
500
POST /api/ordersResourceAccessException from inventory-service
14 failures2 min ago
502
GET /api/payments/{id}Bad gateway from payment-service
3 failures18 min ago
400
POST /api/orders/{id}/cancelFlagged by rule: 4xx on cancel
6 failures1 h ago
500
GET /api/orders/{id}/invoiceNullPointerException in InvoiceMapper
2 failures3 h ago
Service health
order-service customer-service inventory-service payment-service

Every request in. Every call out.

Incoming requests and the outgoing HTTP calls they trigger, captured automatically.

INPOST /api/orders500
OUTGET customer-service200
OUTPOST inventory-servicetimeout
INGET /api/orders/1042200

Decide which errors matter

Rules for 400s and 500s. Ignore the expected 404s, flag every 500 on orders.

application.ymlPH syntax
easydebug:
  rules:
    - match: "5xx"
      path: "/api/orders/**"
      action: flag
    - match: "404"
      action: ignore

RabbitMQ, tracked

Message traffic in the same dashboard as your HTTP requests.

Exchange / queueExample data
PUBorders.eventsorder.created
CONinventory.reserveorder.created
CONnotifications.emailorder.created
PUBorders.eventsorder.cancelled
CONinventory.releaseorder.cancelled

Health checks, 24/7. Plus a status page.

Know a service is down before users tell you. Share one status page with your team.

Order platformStatus page Example data
Copy share link
order-serviceOperational
customer-serviceOperational
inventory-serviceDown
payment-serviceOperational
Last 30 daysToday

Running in 5 minutes.

One Spring Boot app. Nothing else to deploy.

PH Artifact coordinates, version and config keys below are placeholders until the starter is published.

  1. Add the dependency

    PH coordinates
    <!-- pom.xml -->
    <dependency>
      <groupId>[com.easydebug]</groupId>
      <artifactId>[easydebug-spring-boot-starter]</artifactId>
      <version>[version]</version>
    </dependency>
    // build.gradle.kts
    dependencies {
        implementation("[com.easydebug]:[easydebug-spring-boot-starter]:[version]")
    }
  2. Configure it

    application.ymlPH keys
    easydebug:
      app-name: order-service
      # defaults cover the rest [confirm]
  3. Open the dashboard

    Run the app, hit an endpoint, watch the request land.

    localhost:[port]/[path]PH URL
    GET/api/orders/1042200just now
    GET/actuator/health2004 s ago
    Waiting for the next request

Small enough to forget it's there.

[X] MB added to your app PH
[Y]% request overhead on [benchmark] PH
1 dependency confirm
Today EasyDebug One app. 5 minutes. Find the bug.
When you outgrow it OpenTelemetry Many services, distributed tracing, a full backend.

Built to be your first step, not your last. When you need tracing across your whole system, move to OpenTelemetry.

Stop digging through logs. Start fixing problems.

Add EasyDebug to one service today. It takes about 5 minutes.

<artifactId>[easydebug-spring-boot-starter]</artifactId>

PH repository URL and artifact name