By Pascal Rijzinga

Virtual Workspace Monitor

A standalone monitoring dashboard for Omnissa Horizon environments — sessions, infrastructure, capacity, and alerts in one place.

User Guide
Covers v1.4.1
Developed by Pascal Rijzinga

01 — What is Virtual Workspace Monitor?

A quick orientation before you start.

Virtual Workspace Monitor is a lightweight, self-hosted dashboard that gives you a real-time and historical view of an Omnissa (VMware) Horizon VDI environment: active sessions, Connection Servers, UAG Gateways, ESXi hosts, desktop pools, and a connected load balancer — all in a single browser tab.

It runs as one standalone application. There is no database server to install and no cloud dependency: it connects directly to your existing Horizon, vCenter, Active Directory, and load balancer APIs, and keeps its own lightweight history on disk.

Why this exists Built as a free, self-hosted alternative for teams who want the visibility of a full VDI monitoring suite without the licensing cost or external dependencies.

02 — Getting Started

This is the part that matters most — get this right and everything else follows.

What you receive

Virtual Workspace Monitor is distributed as a single application folder. No Python or other runtime installation is required — everything needed to run it is bundled inside the .exe.

Horizon-Monitor\ ├── HorizonMonitor.exe ← double-click this to start ├── dashboard.html ← the web interface, read once at startup ├── chart.js ├── fonts\ ├── logs\ ← daily log files, kept 14 days (created on first run) ├── config.json ← your settings and credentials (created on first run) ├── horizon_history.json ← minute-by-minute history, last 30 days ├── horizon_history_daily.json ← one summary row per day, last 12 months ├── horizon_sessions.json ← session log, last 30 days ├── horizon_alerts.json ← alert history, last ~500 events └── horizon_license_history.json ← license usage snapshots, last ~60 days

All of these except HorizonMonitor.exe, dashboard.html, chart.js and fonts\ are created automatically the first time the application needs them — there's nothing to set up by hand. See below for what each one tracks and how long it's kept.

Place the whole folder anywhere convenient — a local drive or a network share both work. Nothing needs to be installed to the system; the application is entirely self-contained within this folder.

First launch

  1. Start the application. Double-click HorizonMonitor.exe. A dark console window opens, and your default browser opens automatically to the dashboard.
  2. Create the admin account. On first run, you're asked to create the first administrator account. This is a local account stored inside config.json — separate from your Active Directory accounts, and your fallback way in if AD authentication is ever unavailable.
  3. Follow the Setup Wizard. Right after creating the account, a 5-step wizard walks you through the core connections — see the full walkthrough below.
  4. Let it run for a few minutes. Charts and history graphs need a handful of polling cycles before they show a meaningful trend — this is expected and not a fault.
Keep the console window open
That dark console window is Virtual Workspace Monitor's running server process — it's not just a log viewer. As long as it's open, the dashboard, polling, alerts, and scheduled reports keep running. Closing this window stops the application immediately — the dashboard in your browser will stop responding. Minimize it if it's in the way, but don't close it unless you actually want to stop Virtual Workspace Monitor.
Console window that must stay open
Service account permissions Use a dedicated, read-mostly service account for the Horizon and vCenter connections rather than a personal admin account. The account needs enough rights to query sessions and machines, and — only if you plan to use the restart/rebuild/reset/log-off actions from the dashboard — rights to perform those actions too.

Setup Wizard walkthrough

The wizard covers the four connections one at a time. Horizon, vCenter, and Active Directory are required to continue; Email Reports and the Load Balancer step can be skipped and configured later in Settings.

0. Create the admin account. Choose a username and a password meeting the shown requirements. This account can also sign in via AD later if you set that up — this is just the fallback local account.
Welcome screen - create admin account
1. Horizon Connection (required). Your Connection Server(s), domain, and a service account. This is the one connection Virtual Workspace Monitor cannot function without.
Step 1 of 5 - Horizon Connection
2. vCenter Connection (required). Once saved, the wizard automatically checks vCenter for ESXi hosts. If it finds any, it asks whether they all have the same specs — answer "Yes" and fill in RAM/CPU once to apply it to every host in one go. Answer "No" to configure hosts individually later in Settings → ESXi Specs.
Step 2 of 5 - ESXi hosts detected, same specs question Step 2 of 5 - RAM and CPU filled in, saved
3. Active Directory (required). Used to resolve usernames from SIDs in sessions and logs. Needs an account with LDAP read permissions. See the troubleshooting note below if the Base DN order trips you up — it's a common mistake.
Step 3 of 5 - Active Directory
4. Email Reports (optional — skippable). SMTP settings for the scheduled daily/weekly summary reports. Skip this if you don't want email reports yet; it can be turned on later in Settings → Reporting.
Step 4 of 5 - Email Reports
5. Load Balancer (optional — skippable). This integration is built specifically for Kemp LoadMaster. If your load balancer is a different brand, skip this step — Virtual Workspace Monitor doesn't have a generic load balancer integration.
Step 5 of 5 - Load Balancer
All set. The core connections are configured. A "Finish setting up" reminder appears on the Dashboard, pointing to the remaining optional settings: ESXi Specs (if skipped above), Alert Thresholds, Email Reports (if skipped), and Branding. These all work fine with their defaults — review them whenever it's convenient, not before you can start using the dashboard.
Setup complete - Go to Dashboard
Common Active Directory mistake The Base DN must follow the same order as your domain name, read right to left: for example.local that's DC=example,DC=local — not DC=local,DC=example. Getting this reversed is an easy typo and produces a confusing "invalid server address" error that has nothing to do with the server address itself.

Data files & retention

Virtual Workspace Monitor keeps its own history independently of Horizon itself, by polling on a schedule (interval configurable in Settings) and appending each result to a small set of local files next to HorizonMonitor.exe. Nothing is sent anywhere else. Each file has a fixed retention window — older entries are automatically trimmed off so the files never grow indefinitely.

FileWhat it tracksRetentionFeeds into
config.jsonConnections, thresholds, branding, users — every setting on the Settings page. Passwords are DPAPI-encrypted, tied to the Windows account and machine that saved them.Kept until changedEverywhere
horizon_history.jsonOne snapshot per poll (sessions, pools, servers, etc.)Last 30 days, minute-by-minuteCharts tab, short-term trends
horizon_history_daily.jsonOne aggregated row per day (peak/average sessions, peak unique users)Last 12 monthsHistory tab, long-term trends and capacity forecasting
horizon_sessions.jsonEvery individual session that has been seen, with start/end time and statusLast 30 daysSession Log tab
horizon_alerts.jsonEvery alert that fired, and when it resolvedLast ~500 events (roughly a month at typical volume)Alerts tab history
horizon_license_history.jsonA snapshot of license usage per poll cycleLast ~60 daysLicense usage graph in Settings

Because everything lives in plain files next to the executable, backing up Virtual Workspace Monitor is as simple as copying the whole folder — there's no database to export. Deleting any one of these files is also safe: the application recreates it empty on the next write and simply starts that particular history over.

03 — Dashboard Tour

The sidebar is grouped into three sections — Live, History & Analysis, and Management — so it's clear at a glance which tabs show what's happening right now versus what happened in the past. Every page also opens with a short intro card explaining what you're looking at, so this tour is just a quick reference.

Dashboard

Dashboard

The at-a-glance landing page. Top row — KPI cards: four clickable cards give you the headline numbers: Active sessions (with the connected / disconnected split and today's peak time), Idle > 30 min (count plus the longest idle session), Available machines (with a capacity bar that turns amber and red as headroom shrinks), and Infrastructure (Connection Servers, UAG Gateways and ESXi hosts as green/red status dots, plus the number of days until the earliest certificate expires). Each card jumps to the relevant tab. Row 2: At a Glance status summary (left) plus the Live Activity Feed (right) — a real-time scrolling event stream showing logins, logoffs, disconnects, reconnects, and machine errors as they happen. Row 3: Pool Health scores showing per-pool health from 0-100 based on capacity, available machines, errors, and disconnect ratio — click any pool to jump to its sessions — plus VMs per ESXi Host, Session Overview, and Pool Overview.

My Dashboard

Your own, personal layout — pick which widgets you actually want to see, drag them wherever you like and resize them to fit. Covered in full in the next chapter.

Live

What's happening right now — live status and, where relevant, direct actions.

Sessions

The live, filterable list of every current session. Click any row to open a combined detail popup with avatar, colored status/duration/protocol boxes, session info (location, client, agent, UAG), live Blast/PCoIP quality metrics (latency, fps, packet loss, bandwidth) with colored indicators, and action buttons (disconnect, log off, restart machine). Disconnected sessions are highlighted in amber. A separate Disconnected Sessions list shows exactly how long each one has been disconnected. The Sessions Today vs Yesterday card opens with four summary tiles (Connected, Disconnected, Peak today with its time, Peak yesterday with its time) above a gradient chart; hover the chart for exact values at any hour. The External / Internal Night Sessions card lists sessions that were started within the configured night window (Settings → Alerts, default 22:00–06:00), with the route (via UAG = external, via broker = internal) shown per row. Click the card for the full list with an All / External / Internal filter.

Infrastructure

Connection Servers, UAG Gateways, ESXi hosts, and certificate expiry — the components that sit between users and the desktop pools.

vCenter

ESXi host resource usage, VM power state per host, datastore capacity, and — where NVIDIA GPUs are present — per-host GPU utilization, memory, and temperature, all pulled directly from vCenter.

Pools

A dedicated overview of every desktop pool with health scores (0–100), calculated from capacity, available machines, errors, and disconnect ratio. Each pool card shows six metrics (sessions, capacity, machines, available, errors, disconnect ratio), status pills (enabled/disabled, provisioning active/paused, floating/dedicated), golden image and snapshot name, last provisioning date, recompose status, naming pattern, and AD entitlements. Searchable and filterable (all pools, issues only, disabled). Click any pool to open a detail popup with active sessions, machine list, and full configuration. A health score legend explains the thresholds: 80–100 healthy (green), 60–79 attention (amber), below 60 critical (red). On the Dashboard, a compact pool summary shows only pools with issues.

Machines

The full VM inventory across all pools, with bulk actions (select multiple machines with checkboxes, then restart/reset/rebuild them all at once) and per-machine actions. Click any row to open a detail popup with colored CPU/Memory/vGPU/CPU-ready tiles, a datastore/VLAN/IP/agent info grid, recent session history on that machine, and action buttons. Error machines are highlighted in red, maintenance machines in yellow. Where vCenter and pyvmomi are available, each machine also shows live CPU/memory usage, its vGPU profile, datastore, VLAN, and IP address in the table.

Load Balancer

Virtual Service and Real Server status, connection distribution, and backend health for your connected load balancer.

History & Analysis

Looking back — trends, patterns, and searchable records, rather than the live state.

Charts

Visual breakdowns of today's activity: sessions per pool, session duration, protocol distribution, and pool occupancy over the day. Resets each day.

History

Longer-term trend graphs (days to months): session peaks, weekday patterns, capacity forecasting, uptime SLA tracking, and a per-pool breakdown of how many machines were actually powered on each day.

Session Log

A searchable historical record of past sessions (default: last 30 days), plus per-user statistics such as total time connected. The Users Overview table lists everyone, with its own search box — click any user (or one of the Top Users) to open their full history: every session, with times and machines. For who's online right now, use Sessions instead.

User Activity

A per-user overview aggregated from the session log: when each user was last seen, which machine they used, how many active days (correctly counting persistent desktop usage where a single session spans multiple days), how many sessions, and their average session duration. Click any row to open a detail popup with colored stat boxes and the user's sessions. If the user is online right now, their active session is shown separately at the top with a live badge, machine name and running time — click it to jump straight to the full session detail (client, agent, gateway, quality metrics, actions). Previous sessions are listed below and are also clickable for a summary. Sortable, searchable, with CSV export.

Audit Log

The official Horizon audit trail — administrator logins, REST API access, and configuration changes — with search and filters for severity, module, server, and date range. A noise filter (on by default) hides routine login/logout chatter and transient vCenter connectivity blips, so the log stays focused on what's actually worth reviewing. This is separate from Session Log above: that one tracks user sessions, this one tracks administrative and system events.

Management

Alerts

Everything currently above a configured threshold, what recently self-resolved, and a full timeline for spotting recurring problems. Alert cards are color-coded by severity (red for critical, amber for warning, blue for info). Each alert type can be individually snoozed for 15 minutes to 8 hours.

Settings

Connections, ESXi specs, alert thresholds, scheduled email reports, license usage and expiry tracking, and user access control — covered in the next two sections.

Finding your way around

A search icon in the top bar opens a quick-search overlay: type a few characters and it searches sessions, machines, pools, infrastructure, and settings pages all at once, grouped by category. Selecting a result jumps straight to it — no need to remember which tab something lives on.

Dark mode

Click the moon icon in the top-right corner of the topbar (or press D on your keyboard) to toggle between light and dark mode. Your preference is remembered between sessions.

Keyboard shortcuts

For quick navigation without a mouse — active whenever a text input isn't focused:

KeyAction
1 – 9Jump to sidebar tabs (1 = Dashboard, 2 = My Dashboard, 3 = Sessions, etc.)
0Settings
RRefresh all data
/Open search
DToggle dark mode
EscClose modals and popups

Deep links

Each tab updates the URL hash (e.g. #machines, #user-activity). Share or bookmark a URL to open the dashboard directly on a specific page.

Live Activity Feed

The Live Activity Feed on the Dashboard shows a real-time stream of events: user logins, logoffs, disconnects, reconnects, and machine error/recovery events. Events are detected by comparing the current session and machine state with the previous poll cycle — no extra API calls are needed. The feed shows the 15 most recent events with colored icons (green for logins, amber for disconnects, red for errors) and timestamps. A pulsing green dot indicates the feed is live.

Toast notifications

Actions like restarting a machine, performing bulk operations, or managing user accounts show a brief slide-in notification (toast) in the top-right corner instead of a browser popup. Green for success, red for errors. Toasts disappear automatically after a few seconds.

Session quality

Click any active session row to see live Blast or PCoIP performance metrics: round-trip latency, frame rate, packet loss, and bandwidth. Each metric is color-coded (green = good, amber = fair, red = poor) with a progress bar. Quality data is fetched on-demand per session to avoid Horizon API rate limits.

Pool health

Each pool's health score (0–100) is calculated from four factors: capacity percentage, available machines, error machine count, and disconnected session ratio. The Pools tab shows the full breakdown per pool with a color legend (green 80–100, amber 60–79, red below 60). On the Dashboard, a compact summary shows only pools that need attention, with a link to the full Pools tab.

Login speed trending

The Charts tab shows a color-coded bar chart of average logon time per day over the last 7 days. Green bars indicate fast logins (under 40 seconds), amber for moderate (40–60s), and red for slow (over 60s). If one day is significantly slower than average, an anomaly banner highlights it. Logon timing data is collected each poll cycle and stored in the history file.

Week comparison

The Dashboard shows a "This week vs last week" section with four metrics: average sessions, average login speed, error events, and disconnect percentage. Each metric shows the current value, a colored arrow indicating improvement or decline, and last week's value for reference.

CSV export

The Sessions and Machines tables have a CSV download button in the toolbar. It exports the currently filtered data as a CSV file with UTF-8 encoding and BOM for correct display in Excel. The filename includes the current date.

Quick actions

When At a Glance shows error machines, each machine name is clickable and opens the machine detail popup directly. A "Restart all" button restarts all error machines at once (with confirmation). When 3 or more machines are in PROVISIONING_ERROR simultaneously, a separate amber banner warns of a possible vCenter or storage issue.

Machines that are simply in between states — Deleting (an instant clone being refreshed after logoff), Maintenance, Already used, Drain mode — are listed separately in a grey "in a transitional state" block, with the actual state next to each name. They don't count as errors, don't get a Restart button and never raise an alert. Before 1.4.1 they were lumped in with the real errors, which made the count look worse than it was.

Machine error alerts

The alert engine monitors machines for error states (Error, Agent unreachable, Agent config error, Customization error, Missing) and provisioning failures (Provisioning error). Both have configurable thresholds under Settings → Thresholds & Alerts: the warning and critical thresholds for machine errors, and the bulk threshold for provisioning errors. When the bulk provisioning threshold is reached, a critical alert fires with the affected pool names, indicating a possible vCenter or storage problem. The Dashboard, the Machines tab and the alert engine all use the same list of what counts as an error, so the numbers agree with each other.

Print

The printer icon in the topbar prints the currently active tab. The print layout hides the sidebar, topbar, and buttons, showing only the content on A4 paper.

04 — My Dashboard & Widgets

The main Dashboard is a fixed, one-size-fits-all layout. My Dashboard is the opposite: build your own, with only the widgets you care about, placed and sized however you like.

Every person who logs in gets their own, private layout — nothing here is shared between users. It starts empty, and stays empty until you add something.

Adding widgets

There are two ways to add a widget to your personal dashboard:

Widgets look exactly like the original

A widget on My Dashboard is the same view as the card it came from — same layout, same colours, same tooltips, same click-throughs. Under the hood, each widget either shares its rendering code with the original card or is a live mirror of the original chart, so the two can never drift apart. If a card on a tab gains a new column or a new tile, the widget picks it up automatically.

Chart-based widgets (everything from the Charts, History, vCenter and Infrastructure tabs) mirror the chart from their source tab. When you open My Dashboard, the source tabs are refreshed quietly in the background so those widgets have data to show; in the rare case a source hasn't finished loading yet, the widget says so and retries for a few seconds.

Arranging your layout

My Dashboard is a free-form grid — think of the widgets as windows you can move around and resize:

Every change — adding, removing, moving, resizing — saves automatically to your own account; there's no separate save step, and reloading the page brings back exactly the layout you left.

Not every widget is available as a quick "+" button A handful of widgets (Session Summary, GPU Summary, Alert History, and a couple of others) don't correspond to one specific existing card, so they're only reachable through the Add Widget picker on the My Dashboard page itself, not via a "+" button elsewhere.

05 — GPU Monitoring

For environments with NVIDIA GPUs in their ESXi hosts (vGPU-enabled Instant Clone pools, for example).

Each ESXi host card under vCenter shows a GPU section alongside its Memory and vCPU usage — one tile per physical GPU on that host, with utilization %, memory used, and temperature. Tiles are color-coded so a busy or hot GPU stands out immediately:

ColorUtilizationMeaning
Grey0%Idle
Green1–59%Normal use
Amber60–84%High load
Red85%+Very high — on a shared GPU, other VMs on the same physical card may be affected

A legend showing these same ranges sits at the top of the ESXi Hosts card as a reminder.

Under History, a GPU Trend chart tracks utilization and memory used over time — a separate line per host by default, or switch the dropdown to a specific host to break it down to its individual GPUs instead. A second dropdown picks the time range: 7, 30, or 90 days.

Per-VM resource stats

The Machines table shows, per virtual machine: live CPU and memory usage, its assigned vGPU profile (if any), the datastore it lives on, its VLAN/port group, and its IPv4 address. Opening a machine's detail view adds CPU ready time, memory active, disk and network adapter detail, VMware Tools status, uptime, and VM hardware compatibility.

CPU ready time is worth watching Unlike CPU usage %, CPU ready time shows how long a VM had to wait for CPU time from the host rather than how much it used. A VM with low CPU usage but high ready time points to host-level oversubscription — a common, easy-to-miss cause of "slow" VDI sessions that CPU usage alone won't reveal. The detail view flags this combination automatically.
Memory % is not meaningful on vGPU machines Memory % is calculated from vSphere's active-memory estimate (also exposed by VMware Tools as "guest memory usage" — these are the same underlying number, not two independent measurements). This estimate relies on the host's memory-ballooning mechanism to calibrate itself. Machines with an assigned vGPU profile require a full memory reservation and cannot be ballooned, so on these machines the estimate settles on a fixed value regardless of actual load — it does not reflect real memory pressure. The Machines table and detail view show this figure in grey with an info icon on vGPU machines as a reminder; treat it as "not available" rather than as a real reading. There is currently no reliable way to get true in-guest memory usage without querying each machine directly (e.g. over WinRM), which does not scale well across a large VDI estate and is not implemented here.

The GPU framebuffer limitation above still applies here: a VM's vGPU profile (which reveals its reserved framebuffer size, e.g. "A16-2Q" = 2 GB) can be read, but live framebuffer usage per VM cannot — only per host, for the same vCenter 8.0.3 reason.

06 — Branding & Modules

Two settings worth visiting once, right after setup.

Branding

Under Settings → Branding, set your organization's name, a short logo initial (1–2 letters), and two accent colors. Because the whole interface is built on those colors, changing them re-themes the header, sidebar, buttons, and charts everywhere at once — no restart needed.

An actual logo image can be uploaded too (PNG, JPG, or SVG, up to 1 MB), replacing the letter-initial everywhere it appears: the top bar, the login screen, and all three email reports. Any aspect ratio works — square or wide — since the image is scaled to fit rather than cropped.

Modules

Not every environment uses a load balancer, and UAG Gateways only matter for external access. Under Settings → Connections, a small "Modules" panel lets you turn either off. Doing so removes the corresponding tab, dashboard tiles, and chart sections everywhere in the app, and stops alerting on that component — so the dashboard only ever shows what's actually relevant to your setup.

Data storage and retention

VWM stores its data in JSON files next to the executable. To keep files manageable, older data is automatically downsampled to a lower resolution — you keep all 30 days of history, but data older than 48 hours is averaged into 5-minute intervals, and data older than 7 days into 15-minute intervals. This reduces the main history file by about 85%. The session log keeps 30 days of individual session records and trims older entries automatically. GPU history follows the same layered approach. All files use atomic writes so a crash mid-save cannot corrupt them.

License

Under Settings → License, Virtual Workspace Monitor reads your license edition, usage model, expiry date, and enabled features directly from Horizon's own license API — nothing needs to be entered manually. Current and historical peak usage (concurrent connections, sessions, and named users) is shown alongside a trend graph that builds up automatically as the application keeps polling over time. The expiry date turns orange inside 90 days and red inside 30, so a renewal never comes as a surprise.

Settings → Changelog lists what's changed release by release. The current version also shows in the top bar and in the About screen (top right of the dashboard), which links straight through to the full changelog.

07 — Users & Access

Not everyone who looks at the dashboard should be able to restart a VM.

Virtual Workspace Monitor supports three permission levels, assignable either to local accounts or mapped automatically from Active Directory group membership (configured under Settings → Access Control):

RoleCan do
ViewerRead-only access to every tab. Cannot change settings or perform any session/machine action.
OperatorEverything a Viewer can, plus session and machine actions (disconnect, log off, restart, rebuild, reset).
AdminEverything an Operator can, plus full access to Settings — connections, thresholds, reporting, and managing other users.

Signing in with an Active Directory account works automatically once AD is connected; the role is determined by which configured AD group the account belongs to. Local accounts (created in Settings or during first-time setup) are a manual fallback and are recommended mainly for the initial admin account.

Two-factor authentication (2FA)

Local accounts can optionally enable TOTP-based two-factor authentication — the same 6-digit rotating code used by Google Authenticator, Microsoft Authenticator, and similar apps. Once enabled, signing in requires both the password and a valid code from the authenticator app.

To set it up: Settings → Access Control → Two-Factor Authentication, click Enable 2FA, scan or type the secret into your authenticator app, and confirm with a code. To disable: same panel, click Disable 2FA (requires your password). This is a per-account, self-service setting — each user manages their own 2FA, admins don't need to be involved.

AD accounts manage MFA through their own domain/conditional access and are not affected by this setting.

Enforced server-side, not just hidden in the UI These roles aren't just about which buttons are visible — the server checks the role on every request. Concretely: every GET /api/* endpoint requires at least Viewer (except /api/health, which stays open so external monitoring tools like PRTG can poll it without logging in); session and machine actions (disconnect, log off, restart, rebuild, reset) require Operator; and Settings, reporting, and server restart/stop require Admin. If auth is turned off (Settings → Access Control), none of this changes anything — everyone is treated as Admin, exactly as before.

08 — Alerts & Reports

The dashboard watches thresholds so you don't have to.

Every 60 seconds, Virtual Workspace Monitor checks a configurable set of thresholds — disconnected session counts, long idle sessions, session peaks, Connection Server/UAG availability, ESXi memory usage, certificate expiry, vCPU overcommit ratio, datastore usage, machine and provisioning errors, pool capacity, night sessions, outdated clients, and red vCenter alarms. When a value crosses its threshold, an alert is raised and, if configured, an email is sent immediately. When the value returns below threshold, the alert clears itself automatically — no manual acknowledgement needed.

This runs on the server, not in your browser. Nobody needs to have the dashboard open for alerts to fire — that's the whole point of it. (Up to 1.4.0 this was not the case: the checks only ran while someone was looking at the dashboard. If you ever wondered why no mail came in at night, that was why.)

vCenter alarms

Red (critical) alarms in vCenter — an expired certificate in VECS, a host that lost a path to storage, a datastore alarm — raise a critical alert in the monitor, with an email like any other alert. Yellow alarms are shown on the Dashboard under At a Glance but don't alert; they're usually informational. The toggle is under Settings → Thresholds & Alerts → vCenter Alarms. Turn it off if you already get these from vCenter itself and don't want them twice.

Thresholds are configured per category under Settings → Thresholds & Alerts, each with an independent warning and critical level.

Maintenance mode

A single toggle under Settings → Thresholds & Alerts → Maintenance & Snooze that suppresses all outgoing alert emails until turned off. A red banner appears at the top of every page while active, showing when it was enabled, so nobody has to wonder why alerts have stopped. Use this during planned maintenance windows.

Per-alert snooze

If you only need to silence one category (for example, Connection Server alerts while you're rebooting a single CS), each alert type has its own Snooze dropdown with durations from 15 minutes to 8 hours. Snoozed alerts automatically resume when the timer expires — no need to remember to turn them back on.

Night window

The Night sessions card on the Sessions tab lists sessions started during off-hours, which is useful for spotting unexpected external access. The window is configurable under Settings → Thresholds & Alerts → Night window (default 22:00 to 06:00). Sessions that came in through a UAG are labelled External; sessions that connected directly to a Connection Server are Internal. Both are listed — the label tells you the route, not whether the session is suspicious.

System Health monitoring

The server runs several background loops independently: the poll cycle (history, alert engine, session log, activity feed), VM statistics, GPU statistics, pool image resolution, and infrastructure monitoring. If any of these hasn't completed a successful round in over 30 minutes, an alert is sent automatically. The current status of each loop — last success time, last error — is visible under Settings → System Health.

Log files

Everything the console window prints also goes to a log file: logs\vwm-YYYY-MM-DD.log next to the exe, one file per day, kept for 14 days and then deleted automatically. The format is JSON Lines — one JSON object per line with a timestamp, a level (info, warning, error) and the message — which reads fine in Notepad++ and is easy to grep or feed into something else. Settings → System Health lists the files with their size and has a "Download all logs" button that gives you a zip. When something misbehaves on a server nobody sits next to, this is where to look first.

Support export

Also under System Health, for admins only: Create support export. It collects the raw responses of about 27 Horizon REST endpoints (pods, sites, connection servers, gateways, pools, machines, sessions, farms, RDS servers, vCenters, licenses) into one zip, so you can show someone exactly how your environment looks when something isn't displayed correctly — without handing over API access or querying the Horizon API by hand.

Before anything is written to the zip, user names, SIDs, machine names, server and gateway names, IP addresses and DNS names are replaced by placeholders (user-001, host-003.example.local, and so on). Placeholders are consistent within one zip, so structure and counts stay intact, but nothing in it points back to a real person or system. Desktop pool and farm names are kept, because entitlements and sessions refer to them; rename them in the JSON files if that matters to you. Lists are cut off at 50 items. meta.json lists every endpoint with its HTTP status — a 403 there means the service account is missing a privilege, which is useful to know on its own.

Nothing leaves your network on its own
The export only runs when an admin clicks the button, and the zip only goes to your Downloads folder. The monitor has no telemetry and no phone-home; the only way this data reaches anyone is if you decide to send it. Open the zip and look through it first.

Two scheduled email reports can also be enabled under Settings → Reporting:

Both can be triggered on demand from the Reporting tab to preview them before relying on the schedule.

09 — Technical Notes

Kept brief — most of this you'll only need once.

Where things are stored

All JSON files are written atomically (via a temporary file + rename), so a crash or forced stop mid-save can never leave a corrupted file behind — at worst, the last write is lost and the previous version stays intact.

VDI host filter

If your vCenter contains hosts that aren't part of the VDI environment (file servers, application servers, etc.), you can filter them out under Settings → ESXi Specs → VDI Host Filter. Pick a cluster from the dropdown for a quick selection, or choose "Select hosts manually" for individual control. The filter applies globally — all widgets, charts, background loops, and machine/datastore lists show only data from the selected hosts. Set to "All hosts" to disable the filter.

Updating to a new version

Replace HorizonMonitor.exe and dashboard.html with the new versions and restart the application. config.json, the horizon_*.json files and the logs\ folder are never touched by an update — your configuration and history carry over automatically.

Building from source

From the folder containing horizon_monitor.py, dashboard.html, and build.bat (not the folder where the app runs from):

  1. Run .\build.bat (with the .bat — PowerShell will complain about an unrecognized command without it).
  2. It asks one question: "Is dit een build om te distribueren naar een andere omgeving...?" Answer N to keep your own settings, passwords, and history (a normal update for yourself). Answer J for a clean build with none of that — for handing to someone else, who'll see the setup wizard on first launch.
  3. The finished, ready-to-run package appears in a new release\ folder — HorizonMonitor.exe, dashboard.html, chart.js, handleiding.html, the fonts\ folder, and (if you answered N) your own config.json and history files.
  4. Copy the whole release\ folder to wherever you want to run it, and start HorizonMonitor.exe.

Backing up

Copy config.json and the horizon_*.json files periodically. That's the entire state of the application; nothing else needs to be backed up.

Network access required

The machine running Virtual Workspace Monitor needs outbound network access to whichever of these you've connected: the Horizon Connection Server, vCenter, an Active Directory domain controller, your load balancer's management interface, and an SMTP server (for email reports). No inbound access is required except from the browsers of people using the dashboard.

Cross-origin (CORS) requests

The dashboard is served and consumed from the same address, so the API only accepts browser requests from that same origin. If you ever need to embed the dashboard's API in another web application on a different hostname or port, add that origin to config.json:

"cors_allowed_origins": ["https://intranet.example.com"]

Anything not on that list, and not the dashboard's own origin, is refused by the browser. Earlier versions allowed any origin (*); that has been tightened in 1.4.0.

Why only Kemp is supported for the load balancer

The Load Balancer section under Settings only works with Kemp LoadMaster — entering the IP address and API key of another vendor (F5 BIG-IP, Citrix ADC/NetScaler, HAProxy, nginx, etc.) will not work, even though the fields don't say so explicitly.

This isn't a missing checkbox somewhere — it's a deeper limitation. The integration doesn't just need an IP and a key; it calls Kemp's specific REST path (/access/<endpoint>?apikey=...) and parses Kemp's specific XML response format (<VS> elements with fields like NickName and Status). Every other vendor uses a completely different API shape, a different authentication method (often tokens or certificates rather than a simple API key), and a different data format. Supporting another vendor means writing a full second integration from scratch, not extending the existing one.

Why UAG Gateways aren't queried directly

Virtual Workspace Monitor never connects to a UAG appliance's own management interface. Everything shown about UAGs — name, status, active session count, version, certificate expiry — comes from the Connection Server's REST API (/rest/monitor/v2/gateways), using the same session already used for sessions, pools, and Connection Server data. No separate UAG credentials are involved.

This is deliberate, not a shortcut: the Connection Server already tracks this information reliably, over the same secure channel Horizon itself uses to manage each UAG — it's the same data you'd see in the Horizon Console. Connecting to each UAG's own admin API directly would mainly add two things: the UAG appliance's own CPU/memory/disk usage (comparable to what's already shown for ESXi hosts), and a more granular breakdown of status per component (Blast gateway, PCoIP gateway, and tunnel reported separately instead of one combined status). Getting there would mean a second, separate connection per UAG with its own credentials and its own API — for a fairly narrow gain, since the day-to-day questions ("is it online," "how many sessions," "is the certificate about to expire") are already answered.

Horizon's built-in API rate limiting

Since Horizon 2406, the Connection Server enforces its own throttling on the REST API — a maximum number of requests per endpoint per 60 seconds, shared across every client that talks to it (Virtual Workspace Monitor, the Horizon Console, and any other tool). Go over the limit and a request gets a 429 response instead of data.

Virtual Workspace Monitor handles this automatically: on a 429, it waits exactly as long as the server asks (up to 30 seconds) and retries once, rather than just failing. At the scale this tool is normally used at — one instance polling one environment at a sensible interval — the default limits aren't a concern. It would only become relevant with a very large environment or an unusually aggressive poll interval.

10 — Troubleshooting

A few things worth checking before assuming something's broken.

For anything not covered here: download the logs from Settings → System Health and open an issue on GitHub. Mention the version shown in the header and your Horizon version.