Agent utilization report issues in Horde dashboard

Hi,

We noticed for a while now that the Agent Utilization Report page from the Horde dashboard didn’t really make sense. The usage values seemed way too low, not all the data seemed visible and the time seemed off. We decided to look into it and found more issues than anticipated. We ended up fixing these on our side but I thought of sharing the list of issues here in case you can make use of it too.

UtilizationReportView.tsx (Dashboard)

  1. Pool dropdown silently drops pools - Pools whose names contain no dash character are excluded from the dropdown due to a split.length > 1 guard. Any single-word pool name never appears.
  2. totalTime not accumulating across bucket hours - For intervals > 1 hour (2h, 4h, etc.), totalTime only captures the last hour’s agent count instead of summing across the full bucket. This makes the y-axis and idle/free time calculations wrong for any non-1h interval.
  3. pool.otherTime dead code / accumulation missing - The code has full infrastructure for an “Other Time” bar segment (declaration, chartPoints.push block, reset) but the accumulation line poolOtherTime += pool.otherTime was never added. As a result Other Time never appears. If activated, displaying pool.otherTime alongside stream segments for multi-pool selections would double-count work already credited to the owning pool, causing bar totals to exceed 100%.
  4. Y-axis tick labels duplicate for multi-hour intervals - The y-axis upper bound rounding uses a fixed step of 20 (raw machine-hours), but the formatter divides by bucketInterval for display. For a 2h interval this produces labels like 0, 1, 1, 2, 2, 3, 3.
  5. Pool selector title shows internal category keys - The Dropdown onRenderTitle does not filter out g-{prefix} group keys, so selecting a pool category causes the title to repeat the pool name once per matching key (e.g., “Windows, Windows, Windows, Windows”).

UtilizationController.cs (Server)

  • Timezone offset not applied to start date - startDateOffset applies tzOffset only to the end date. The start date always resolves to UTC midnight, not local midnight. For non-UTC users this shifts the returned data window, resulting in blank bars and data appearing at the wrong local hours. Additional note: the dashboard is using the deprecated /api/v1/reports/utilization/{endDate} endpoint (marked [Obsolete] in the server source, with a comment “Logic here is a bit messy”). Migrating to /api/v1/utilization (which accepts explicit after/before UTC parameters) would eliminate the timezone ambiguity entirely and resolve this bug as a side effect.

API Design Limitation

  • No unique agent count per pool combination - pool.numAgents double-counts agents shared across pools, and the top-level hour.numAgents covers the whole fleet. Makes accurate idle time calculation impossible for multi-pool selections on the client.

For reference this is data structure in the API response as far as we can tell:

GetUtilizationTelemetryResponse
├── startTime / finishTime       — the hour this bucket covers
├── numAgents                    — unique physical agent count across the entire fleet (not double-counted)
├── adminTime                    — always 0 (set by server but never populated)
└── pools[]
      └── GetUtilizationTelemetryPool
            ├── poolId
            ├── numAgents        — agents that have this pool in their list + stopped instances
            ├── adminTime        — machine-hours on leases with no pool/stream (conform, maintenance, etc.)
            ├── otherTime        — machine-hours doing work for a DIFFERENT pool's streams
            ├── hibernatingTime  — machine-hours of stopped/hibernating auto-scaled instances
            └── streams[]
                  └── GetUtilizationTelemetryStream
                        ├── streamId
                        └── time — machine-hours spent on jobs belonging to this stream

I hope you’ll find this useful.

Cheers, Daniel

[Attachment Removed]

Thank you for putting this report together for us. We really appreciate it!

I’ve spent some time today reviewing each item, confirming the behavior, and writing up the feedback for the engineering team.

I’ll share this with them and let you know when I get the tracking number for each bug fix or feature request.

[Attachment Removed]