---
module: analytics.incidents
title: Incident Trends
tab: Internal
order: 20
audience: internal
---

> Ops/support view for the **Incident Trends** tab (analytics.incidents). Grounded in `hiveops-analytics` + `hiveops-incident` source, 2026-07-01.

## What actually powers this screen

The tab is **not** backed by the analytics snapshot store. It is a **live, synchronous pass-through**:

```
Browser → GET /api/analytics/incident-trends  (hiveops-analytics)
        → GET /api/journal-events/activity?hoursBack=24  (hiveops-incident)
        → journal_events table
```

`IncidentTrendsService` forwards the **caller's own JWT** downstream and computes the 4 charts in-memory on every request. No caching, no DB write, no Kafka for this feature. If the incident service is down or slow, this tab is empty — nothing here reads analytics-local tables.

## Roles / access

- The endpoint has **no `@PreAuthorize`** — any authenticated JWT can call it. There is no MSP_ADMIN/BCOS_ADMIN gate on Incident Trends.
- **Data is institution-scoped downstream.** `hiveops-incident` calls `InstitutionContext.resolveScope()` on the forwarded token:
  - `ROLE_CUSTOMER` / `ROLE_MSP_ADMIN` → scoped to their granted institution keys (sees only their ATMs).
  - `BCOS_ADMIN` / `ADMIN` / `QDS_ADMIN` / `USER` → unrestricted (all institutions).
- So a support user seeing "less data than expected" is usually a **scoped role**, not a bug.

## First things to check when it misbehaves

1. **Whole tab empty / "No data" everywhere** → the downstream call failed. `IncidentTrendsService.fetchActivityEvents` swallows exceptions and returns an empty list, logging `IncidentTrends: failed to fetch activity events: ...`. Check `hiveops-analytics` logs (Loki, service VM) for that line, then check `hiveops-incident` health.
2. **Analytics can't reach incident** → verify `INCIDENT_SERVICE_URL` (default `http://hiveops-incident-backend:8080`). Wrong/stale hostname = every trends call empties out.
3. **401/403 from downstream** → the forwarded JWT lacks incident access, or is expired. The user's token is passed verbatim; there is no service account.
4. **Customer sees "Not enough data" on the line chart** → see Known quirks; this is expected with current code, not an outage.
5. **Only recent stuff shows** → the window is **hard-coded to the last 24 hours** (`hoursBack=24`), despite the "30-Day" chart title. Older events are simply not fetched.

## Known quirks (expected behavior of current build)

- **30-Day Incident Trend line chart always shows "Not enough data."** `dailyCounts` is seeded with **today only**, so it always has exactly one point; the frontend requires ≥2 points to draw a line. See uncertainties — this is a real defect, not a config issue.
- **Recurring Failures table is effectively always empty.** The service reads `atmId` as a String, but the incident DTO serializes `atmId` as a numeric `Long`, so every event is skipped. Do not tell users "no recurring failures = healthy fleet" from this tab. (real bug — noted for engineering.)
- **Event Category Breakdown never shows an "Operations" bar.** Operational event types (`OPERATOR_ACTION`, etc.) classify to **OTHER**, not OPERATIONS, even though the customer copy lists Operations. Categories the backend actually emits: `HARDWARE`, `CASH`, `NETWORK`, `POWER`, `AUTH`, `SYSTEM`, `OTHER`.
- **Peak Hours Heatmap and Category bars are the reliable panels** — they only depend on `eventTime`/`eventType` (both strings) and work as intended over the 24h window.

## Where to look

| Concern | Location |
|---------|----------|
| Trends endpoint | `hiveops-analytics` → `controller/IncidentTrendsController.java`, `service/IncidentTrendsService.java` |
| Upstream data | `hiveops-incident` → `controller/JournalEventController.java` (`/activity`), `service/JournalEventService.java#getActivityEvents` |
| Category mapping | `hiveops-analytics` → `service/FleetHealthService.classifyEventType` |
| Frontend | `hiveops-analytics/frontend/src/components/tabs/IncidentTrendsTab.svelte` |

See also [analytics.incidents] Overview (customer copy) and the Architect tab for data-flow detail.
