Trip Health Monitoring
Taxi & Private Hire › Products › Trip › Trip Health Monitoring
Generally available
Continuous monitoring of every active trip for risk conditions — late prediction, stale GPS, allocation risk, tight window, dropoff coord mismatch, dwell time, and others. Each detected risk creates a TripHealthCheck row with a status (WARNING / CRITICAL) and optional auto-resolve date. Operators see warnings on the dashboard; the health resolution system can suggest or take nudge / corrective actions per check. Auto-resolves when the underlying condition clears.
Settings
How operators configure this feature.
Health alerts pile up, and by the time someone reads them the moment to act has often passed. Health Auto-Resolve watches how long each alert stays open against what's normal and steps in when one drags on — suggesting a fix to your team, or, if you allow it, carrying out safe fixes on its own — so problems get handled while they're still small.
Modes: OFF · SUGGEST · AUTO · default OFF
When a trip is predicted to miss its pickup, your dispatch screen sees it — but your other systems don't, unless you tell them. Turn this on and we'll send a webhook to your platform the instant a late-running trip is detected, so you can warn the customer, reshuffle a downstream job, or trigger whatever you've built. A circuit breaker watches for trouble: if a large share of trips go late at once — a storm, a road closure — it mutes the individual alerts and sends one "widespread delays" signal instead, so you're informed, not buried. Leave it off and nothing leaves the platform.
On / off · default false
By the time a trip is out looking for a driver, your options are already narrowing. Turn this on and the platform looks further ahead: it studies trips that are still scheduled — not yet released to drivers — and flags the ones heading for trouble, like a busy airport run at a time when few cars will be free. That early warning gives you room to plan: line up a driver, shift a booking, or set expectations with the customer while you still can. It's off by default because forward predictions need your local patterns to settle in first; switch it on once you trust the live warnings.
On / off · default false
When a driver's app stops reporting its location you're flying blind — you can't tell if they're on their way, stuck, or offline. This flags trips where the location has gone silent, with a warning and then a critical alert, so your team can check in before the passenger is left wondering where their car is.
| Setting | Range | Default |
|---|---|---|
| Driver connection lost Flag a trip when the driver's app stops sending its location. | 0–1 | 1 |
| Warn after (s) Seconds with no location before a warning shows. | 60–900 | 300 |
| Critical after (s) Seconds with no location before a critical alert shows. | 120–1800 | 600 |
A trip taking far longer than the route should usually means a driver who's lost, stuck, or detouring. This compares the real elapsed time against the expected drive time and flags trips that slip past your thresholds — so you can step in, rather than hear about it from an angry caller.
| Setting | Range | Default |
|---|---|---|
| Trip running slow Flag trips taking much longer than the expected drive time. | 0–1 | 1 |
| Warn at (× expected time) Warn when a trip takes this many times longer than expected (1.3 = 30% over). | 1.1–5 | 1.3 |
| Critical at (× expected time) Critical alert when a trip takes this many times longer than expected (1.8 = 80% over). | 1.3–10 | 1.8 |
A booked pickup or delivery window is a promise to the customer. This flags trips at risk of breaching that window while there's still time to act — reassign, re-route, or warn the customer — instead of finding out once the trip is already late.
| Setting | Range | Default |
|---|---|---|
| May miss booked time Flag trips at risk of missing their booked time window. | 0–1 | 1 |
| Warn when this close (s) Warn when only this many seconds are left before the booked time. | 600–3600 | 1800 |
For pre-booked trips, the assigned driver needs to be online and ready as pickup approaches. This flags a scheduled driver who hasn't come online in time, so you can reassign before the passenger is standing on the kerb waiting for a car that was never coming.
| Setting | Range | Default |
|---|---|---|
| Driver not online in time Flag a scheduled driver who has not come online when expected. | 0–1 | 1 |
When a trip ends up with more passengers than the vehicle has seats — usually after a last-minute edit — someone gets left behind. This flags trips that exceed the vehicle's capacity so you can fix the vehicle or the booking before the driver pulls up to a crowd that won't fit.
| Setting | Range | Default |
|---|---|---|
| Too many passengers Flag trips where passengers are more than the vehicle's seats. | 0–1 | 1 |
A driver can accept a trip and then not actually set off. This flags trips that have been assigned too long without the driver starting — so a stalled job doesn't quietly eat into the pickup time before anyone notices it's going wrong.
| Setting | Range | Default |
|---|---|---|
| Assigned trip not started Flag a driver who has not started a trip given to them. | 0–1 | 1 |
| Warn after (s) Seconds after getting the trip without starting it before a warning. | 120–3600 | 900 |
| Critical after (s) Seconds before a critical alert. | 300–7200 | 1800 |
A driver parked at a stop far longer than expected might be waiting on a no-show, stuck at a loading bay, or simply forgot to move the trip on. This flags overlong stops so your team can nudge the driver and keep the trip — and the ones behind it — moving.
| Setting | Range | Default |
|---|---|---|
| Stopped too long Flag a driver who stays too long at a stop. | 0–1 | 1 |
| Warn after (s) Seconds stopped at a stop before a warning. | 120–3600 | 900 |
| Critical after (s) Seconds stopped before a critical alert. | 300–7200 | 1800 |
| No-show grace (s) After a no-show, wait this long before the stopped-too-long alert can fire again. | 60–900 | 300 |
Some trips sit waiting while offers are turned down or no one suitable is in range. This flags trips that have been unmatched too long, with a warning and then a critical alert, so your team can intervene before a waiting passenger becomes a complaint.
| Setting | Range | Default |
|---|---|---|
| Trip not matched Flag a trip that is stuck waiting for a driver. | 0–1 | 1 |
| Warn after (s) Seconds waiting for a driver before a warning. | 120–3600 | 600 |
| Critical after (s) Seconds waiting before a critical alert. | 300–7200 | 1200 |
Some trips are in trouble from the start — too few drivers free, no one with the right vehicle, or rejection after rejection. This flags those trips early so you can widen the net, call in supply, or set expectations, rather than watch a trip quietly fail.
| Setting | Range | Default |
|---|---|---|
| May not get a driver Flag trips that may go uncovered — few drivers free, or many rejections. | 0–1 | 1 |
| Busy threshold (trips per driver) How many waiting trips per free driver counts as high demand. | 1.5–10 | 3 |
| Low-supply driver count Flag a trip as low-supply when this many or fewer drivers are free nearby. | 0–10 | 2 |
| Right-vehicle threshold Flag a capability problem when fewer than this share of nearby drivers can serve the trip (0.3 = 30%). | 0.05–1 | 0.3 |
| Rejections before flagged Number of driver rejections before a trip is flagged as at risk of going uncovered. | 1–10 | 3 |
This predicts whether the driver will reach the pickup after the booked window and flags trips that look likely to run late — early enough to act, and optionally to notify outside systems. Lateness becomes something you manage in advance, not something you discover after the fact.
| Setting | Range | Default |
|---|---|---|
| Likely to run late Flag trips that look likely to arrive late. | 0–1 | 0 |
| Notify when later than (s) Show a notice when a trip is expected to be more than this late. | 180–1800 | 300 |
| Pause alerts above (% late) Stop sending late-trip notifications once this share of trips are running late (avoids alert storms). | 5–50 | 15 |
| Resume alerts below (% late) Resume late-trip notifications once the late share drops back below this. | 3–40 | 10 |
Related
Fields
| Field | Type | Description |
|---|---|---|
trip | Trip | The Trip this check belongs to. One trip can have many active checks (different `checkName`s); composite index `idx_trip_check_active` makes active-check lookups O(1). |
checkName | string | Identifier of the check that raised this row ("late_prediction", "stale_gps", "allocation_risk", "tight_window", "dropoff_coord_mismatch", "dwell"). One row per (trip, check, active-state). |
status | string · HEALTHY | WARNING | CRITICAL | Current severity — WARNING (visible, no action required) or CRITICAL (operator attention required). Escalation paths recorded on the `escalatedTo*` fields. |
message | string | Human-readable description rendered on the dashboard ("Trip predicted to be 12 min late", "GPS stale for 4 min"). Built by the check at detection time. |
meta | json | Structured payload specific to the check ("predictedLateSeconds", "lastFixAge", projected radius, etc.). Drives nudge / resolution UIs without re-running the detector. |
resolvedDate | integer | Unix timestamp at which the check resolved (condition cleared or operator acted). Null while still active. Indexed for active-check lookups. |
escalatedToWarningDate | integer | When this row first reached WARNING. Set on creation if WARNING-born; set on escalation if it grew from a softer state. |
escalatedToCriticalDate | integer | When this row escalated to CRITICAL. Null when the row never crossed from WARNING to CRITICAL. |
autoResolveScheduledDate | integer | Future timestamp at which auto-resolution should fire if the underlying condition still holds (sustained-condition pattern). Indexed via `idx_auto_resolve` for sweep efficiency. |
resolvedBy | string | Who resolved the check — "SYSTEM" for auto-resolve, an operator G-ID for manual acknowledgements, "DRIVER" for prompts the driver actioned. |
resolutionAction | string | Action taken to resolve ("ack", "reassign", "extended_window", "nudge_accepted", etc.). Lets reporting count operator interventions per check type. |
mutedUntil | integer | Suppression-until timestamp. While `now() < mutedUntil`, this check is hidden from dashboards but kept on disk for audit. |
mutedBy | string | Operator G-ID that applied the mute. Captured for audit logging of suppression decisions. |
mutedReason | string | Free-text reason the operator gave when muting ("known traffic", "ride share late by 10m, customer informed"). Shown in audit logs. |
clientId | bigint | Tenant scope. Every tenant-aware entity carries this; `ClientFilter` enforces row-level isolation on read; the multi-tenancy routing layer (`/client/{clientId}`) sets it at create time. Surfaced only under `admin` / `tripLog` groups — never to end users. |
internalKey | string | Optional client-supplied external reference / idempotency key. When present, lets external systems correlate platform-side records back to their own source-of-truth ids. Not persisted to a column — populated by the request handler when the caller sets it. |
__objectType | string | Discriminator string (entity class short-name) emitted alongside the id in serialized output. Resolved at read time by `getObjectType()`; lets the FE dispatch entity-specific rendering without inspecting the URL. |
id | bigint | Snowflake-style primary key (unsigned BIGINT). Generated by `IdFactory` at create time; surfaced to the FE / API as a `G`-prefixed string and stripped back to plain bigint server-side before Doctrine lookup. |
createdDate | integer | Unix timestamp the row was first persisted. Set in the entity's PrePersist hook; never rewritten on subsequent updates. |
updatedDate | integer | Unix timestamp the row was last touched. Bumped on every commit that hits the Doctrine UoW for this entity; drives FE invalidation + the listing change cursor. |
passiveUpdatedDate | int | Read-through alias for `updatedDate` exposed under different serializer groups. Lets the FE distinguish "real edit" from "background touch" projections without changing the underlying column. |
listingUpdatedDate | int | Listing-projection timestamp surfaced only under the `listMode` group. Driven by `TripCache` and other listing-shape refreshers separately from `updatedDate` so a listing rebuild doesn't trigger detail-page invalidation. |