Two parts: a service and a dashboard
IIS Monitor has two programs, both on the IIS server. A Windows service does all the collecting, and the dashboard shows what it collects.
- The service
IISMonitorruns as LocalSystem and starts with Windows. On every update it reads the IIS configuration, the process table, performance counters, two ETW trace sessions, the TCP table and, if configured, SQL Server. It writes history to%ProgramData%\IISMonitor\history.db, runs the auto blacklist, and streams live snapshots to the dashboard.- The dashboard
IISMonitor.exeis a Windows desktop app. It connects to the service through a local named pipe that only Administrators and SYSTEM can open. If the service isn't running, it runs the same collector itself (standalone mode) so the live view still works.
What is measured, and how
| Metric | Per | Source |
|---|---|---|
| CPU %, private memory, working set, threads, handles | App pool, process | Win32 process APIs on each w3wp.exe and every process it started |
| Process count | App pool | w3wp.exe per pool (several for web gardens) plus child processes: out-of-process ASP.NET Core, PHP FastCGI, iisnode… |
| Disk read/write bytes/sec | App pool, process | Kernel ETW file I/O events, the data Resource Monitor uses; process I/O counters if ETW is off |
| Network sent/received bytes/sec | App pool | The HTTP traffic of the pool's sites (IIS Web Service counters) plus the pool's own outbound traffic |
| Outbound sent/received bytes/sec | App pool, process | Kernel ETW TCP/UDP events: traffic the pool's processes create themselves |
| Bandwidth, requests/sec, connections | Site | IIS Web Service performance counters |
| Requests/sec, active requests | App pool | IIS W3SVC_W3WP performance counters |
| Request queue length | App pool | HTTP Service Request Queues performance counters |
| SQL Server connections | App pool, process | Established TCP connections from the pool's processes to SQL Server ports |
| SQL Server sessions (active / idle) | App pool, process | Optional: sys.dm_exec_sessions, matched by client process ID |
| Database load, blocking, slow queries | App pool | Optional: running requests in sys.dm_exec_requests, sampled every second |
| SQL Server CPU and memory | Server | The local sqlservr.exe process |
| Response time avg / p95 / max, 4xx and 5xx | Site, app pool | IIS's Microsoft-Windows-IIS-Logging ETW provider, including time-taken |
| Each request: client IP, method, kind, URL, status, time, size, user agent | Request, IP | The same ETW events with extra W3C fields, and optional header fields |
| Server CPU and memory | Server | GetSystemTimes, GlobalMemoryStatusEx |
Things worth knowing
CPU, memory, disk and database connections belong to an app pool
IIS runs each application pool in its own processes. If several sites share one pool, those numbers can't be split between them. Requests, bandwidth and response times are still per site. One pool per site gives the clearest picture.
Website traffic doesn't go through w3wp.exe
The kernel driver HTTP.sys owns ports 80 and 443, so Windows charges incoming website traffic to the System process. That is why website traffic comes from IIS's counters. A pool's network total adds its sites' website traffic, credited to the pool running each site's root application, to the outbound traffic its own processes create. Per-process numbers are outbound only, and loopback traffic between a pool's own processes isn't counted twice.
Live response times come from IIS's ETW log target
IIS can write its W3C log to files, to ETW, or both. Enable response times sets the target to File, ETW and turns on the fields s-sitename, cs-uri-stem, sc-status and time-taken if they are off. Log files are written as before. This needs the HTTP Logging role service; sites using central binary logging can't be traced.
Counting SQL Server connections over TCP sees network connections
If an app talks to a SQL Server on the same machine over shared memory or named pipes, there is no TCP connection to count. Add a connection string in Settings: SQL Server then reports the sessions itself, active and idle, and the Database tab lights up.
CPU % is a share of the whole machine
Like Task Manager's Processes tab, 100 % means every core is busy. A single-threaded loop on a 16-core server shows about 6 %.
Idle pools and recycles are handled
Pools without a worker process yet show 0 processes, not an error. Process IDs change on every recycle; IIS Monitor re-maps them on every update.
A light footprint
- Everything it reads already exists in Windows and IIS: process counters, performance counters and ETW events. Nothing is injected into your applications.
- SQL Server is asked one light query per sample; nothing is installed there and no trace is started.
- Nothing listens on the network; the dashboard and service talk over a local named pipe.
- Kernel and IIS tracing can each be switched off in Settings.