---
module: analytics.uptime
title: Uptime
tab: Internal
order: 20
audience: internal
---

> **Internal ops/support.** Grounded in `hiveops-analytics` source (2026-07-01). The Uptime screen is **read-only** — there are no admin buttons, no writes, no fleet actions. When it looks wrong, you are almost always debugging **stale snapshots** or a **failing downstream call**, not user input.

## Who owns it

- **Service:** `hiveops-analytics` (port **8089**, DB **`hiveiq_analytics`**).
- **Endpoint the screen hits:** `GET /api/analytics/uptime` (`UptimeController`).
- **Frontend:** `UptimeTab.svelte`, called via `api.getUptime()` → `${apiBase}/uptime`.

## Roles / access

- **No role gate.** `SecurityConfig` = `.anyRequest().authenticated()`; only `/actuator/health` and `/api/public/**` are `permitAll()`. Any valid JWT can read Uptime — MSP_ADMIN is **not** required.
- The endpoint **forwards the caller's Bearer token** downstream to the incident service. If the caller's token can't read ATMs, the "Currently Down" list comes back empty (the call is caught and logged, not surfaced).

## What the numbers actually come from

| Card / panel | Real source |
|---|---|
| **NOW** ring | Latest `analytics_snapshots` row for **today** (`connectedAtms / totalAtms`). Can be up to **6 h stale**. |
| **7-DAY AVG** / **30-DAY AVG** | Both computed from **today's snapshots only** (see caveat below). |
| **30-Day Trend** chart | `dailyTrend` — currently **today only** (1 point). |
| **CURRENTLY DOWN** count + table + **never connected** badge | **Live** call to incident: `GET /api/atms/paginated?size=500&agentStatus=DISCONNECTED,NEVER_CONNECTED`. Capped at 50 rows, sorted longest-down first. |

So the top-left ring is **snapshot-derived (may lag)** while the down-list is **live**. They can legitimately disagree for a few hours.

## First things to check when it misbehaves

1. **"Not enough data" on the trend / flat 7-day = 30-day numbers** → expected with current code (only today's snapshots are queried). Not a data-loss bug per se — see Common failure modes.
2. **All zeros / NOW ring empty** → no `analytics_snapshots` row for today. Check the snapshot pipeline:
   - `docker compose logs hiveiq-analytics | grep -i snapshot` — look for `Analytics snapshot saved for <date>/<hour>`.
   - Snapshots are written by `SnapshotCollectionService.collect()`: cron **every 6 h** (`0 0 */6 * * *`) **plus** Kafka triggers (incident + journal events). If Kafka is quiet and the cron hasn't fired, today may have no snapshot yet.
   - Force one indirectly by generating an incident/journal event, or wait for the 6-hour cron.
3. **CURRENTLY DOWN empty but you know ATMs are offline** → the live incident call failed or returned empty. `grep "failed to fetch down ATMs"` in analytics logs. Verify incident-backend is up and still serves `/api/atms/paginated`.
4. **Numbers look right in analytics but the snapshot is old** → the collector calls devices/incident/fleet/journal with an **internal service token** (`InternalTokenGenerator`, role `ADMIN`). If a downstream is down, `FleetOverviewService` logs `Failed to fetch ATM summary` and the snapshot stores zeros for that section.
5. **Wrong DB / no rows at all** → confirm prod split env vars `DB_HOST/DB_PORT/DB_NAME/DB_USERNAME/DB_PASSWORD` (analytics does **not** use a single `DB_URL`). Query:
   `SELECT snapshot_date, snapshot_hour, total_atms, connected_atms FROM analytics_snapshots ORDER BY snapshot_date DESC, snapshot_hour DESC LIMIT 5;`

## Common failure modes + fixes

| Symptom | Likely cause | Fix |
|---|---|---|
| Trend chart always says "Not enough data" | `UptimeService` only loads **today's** snapshots → `dailyTrend` has 1 point; frontend needs ≥2 | Product/code issue (see Architect); not a config fix |
| 7-day and 30-day rings show the **same** number | Both = today's average in code | Same — code limitation, not corruption |
| NOW ring stale vs. down-list | NOW from snapshot (≤6 h old), down-list is live | Expected; force a fresh snapshot via a Kafka event if needed |
| Down-list empty / count 0 despite offline ATMs | Incident `/api/atms/paginated` failed or caller token lacks ATM read | Check analytics logs + incident-backend health |
| Whole screen zeros | No snapshot row for today | Check snapshot collector logs, Kafka consumers, cron |
| 401/403 loading tab | Caller JWT expired/invalid (no role issue — any auth works) | Re-login / refresh token |

## Handy commands

```bash
# analytics health + recent snapshot activity
docker compose logs --tail=200 hiveiq-analytics | grep -iE "snapshot|down ATMs|Failed to fetch"

# latest snapshots (DB VM via ProxyJump)
ssh -i ~/.ssh/id_ed25519_hiveiq -J bcosadmin@173.231.195.250 bcosadmin@10.10.10.188 \
  "docker exec hiveiq-postgres psql -U hiveiq -d hiveiq_analytics -c \
   'SELECT snapshot_date,snapshot_hour,total_atms,connected_atms,disconnected_atms FROM analytics_snapshots ORDER BY snapshot_date DESC, snapshot_hour DESC LIMIT 10;'"
```
