Performance Monitor and Data Collector Sets
A practical guide to Windows Performance Monitor’s Data Collector Sets, showing how counter paths, logman.exe, and the Get-Counter cmdlet work together to capture real performance numbers from a problem window nobody was watching live.
A named, reusable definition of what to collect, for how long, and where to store it.
A single measured value inside a performance object, such as % Processor Time.
The command-line tool that creates, starts, stops, and queries Data Collector Sets without opening the perfmon console.
What Is Performance Monitor?
Performance Monitor is the built-in Windows tool for watching and recording how a system is behaving, right down to individual counters like disk queue length or context switches per second. It ships as an MMC snap-in and has been part of Windows in various forms since Windows Vista and Windows Server 2008.
Opening perfmon.exe shows three areas: Performance Monitor, a real-time view of live counter graphs; Data Collector Sets, defined data collection over a given time interval; and Reports, the results a Data Collector Set produced after it ran.
Think of a Data Collector Set as a flight recorder bolted to the server. It does not matter whether anyone is watching when the incident happens, because the recorder was already running before it did.
Why Use a Data Collector Set Instead of the Live View?
The live Performance Monitor graph is useful when you already know something is wrong right now. It is useless for the far more common case: a problem that happens sporadically, five minutes after boot one day and two hours in the next, with no obvious pattern and nobody at the console when it strikes.
Real-time view. Only useful if you are watching at the exact moment the problem occurs.
Runs unattended over hours or days, logging to a binary .blg file with predictable overhead.
What a completed Data Collector Set leaves behind — the evidence you review after the fact.
A Data Collector Set can hold three kinds of data collectors: performance counters, event trace data, and system configuration information such as registry key values. For everyday troubleshooting, a counter data collector covers most cases, and it is the type this post focuses on.
Because the default log format is binary, a multi-day capture stays compact and the overhead of writing it stays low. When it is time to analyse the data, convert it to CSV afterwards with relog rather than re-running the whole capture in a slower text format.
Version Boundaries, Footprint, and Permissions
Data Collector Sets are not a separate Windows feature you install with Install-WindowsFeature. Performance Monitor, logman, and the counter infrastructure underneath them ship in every edition of Windows Server and Windows client going back to Windows Vista and Server 2008, with no additional role to add or remove.
The one real boundary is the graphical console itself. perfmon.exe is an MMC snap-in, so it needs a GUI shell to open. On Server Core installations, which do not run the full desktop shell, reach for logman.exe, relog.exe, or the Get-Counter PowerShell cmdlet instead — they are plain console tools and work identically against the same counters and Data Collector Sets underneath.
Permissions matter more than most admins expect. Two built-in local groups govern access: Performance Monitor Users can view real-time data and change display properties, but cannot create or modify Data Collector Sets. Performance Log Users can manage counters, logs, and alerts remotely without being an Administrator — except that on Windows Server 2016 and later, a member of Performance Log Users cannot create a Data Collector Set at all unless that group has first been granted the Log on as a batch job right through Local Security Policy.
Counter Paths and Creating a Data Collector Set
Every counter is addressed by a path with the same shape, whether you build it in the perfmon GUI, pass it to logman, or feed it to Get-Counter:
\\ComputerName\CounterSet(Instance)\CounterName
| Component | Meaning |
|---|---|
\\ComputerName | Optional. The remote computer to query; omit it and Get-Counter uses the local computer. |
CounterSet | The performance object being measured, such as Processor, Memory, or LogicalDisk. |
(Instance) | Which instance of that object. Use * for every instance or _Total for the aggregate, where the object has instances at all. |
CounterName | The specific measured value inside that object, such as % Processor Time. |
Not every object needs an instance. LogicalDisk requires one, since a server can have several volumes, so its path looks like \LogicalDisk(C:)\% Free Space. Process does not require one to enumerate, so \Process(*)\% Processor Time is valid on its own. Counter names are also localised, so a path built on an English-language system will not resolve on a non-English one. Confirm the exact wording with Get-Counter -ListSet before hard-coding it into a script.
In the Performance Monitor console, a new Data Collector Set is created by expanding Data Collector Sets, right-clicking User Defined, pointing to New, and choosing Data Collector Set. The wizard then offers a choice: create it from a template, or create it manually and select individual counters, their sample interval, and where the log should be written — by default under C:\PerfLogs\Admin.
The command-line equivalent skips the wizard entirely. logman create counter builds the same Data Collector Set in one line, which is what makes it scriptable across many servers at once.
Commands: logman, Get-Counter, and relog
The commands below cover the full lifecycle: create a counter Data Collector Set, run it, inspect what is configured, sample counters directly from PowerShell, and convert a finished log for analysis.
# Create a counter Data Collector Set sampling CPU every 5 seconds,
# capped at 250 MB, writing to the default PerfLogs location
logman create counter perf_log -c "\Processor(_Total)\% Processor Time" -si 00:00:05 -max 250 -o C:\PerfLogs\Admin\perf_log
# Start the Data Collector Set
logman start perf_log
# Stop it once you have enough data
logman stop perf_log
# List every Data Collector Set configured on this system
logman query
# List just the counters inside one Data Collector Set
logman query perf_log
# Remove a Data Collector Set you no longer need
logman delete perf_log
# Take a single live reading of a counter from PowerShell
Get-Counter -Counter "\Processor(_Total)\% Processor Time"
# Sample the same counter every 2 seconds, 3 times
Get-Counter -Counter "\Processor(_Total)\% Processor Time" -SampleInterval 2 -MaxSamples 3
# Sample continuously until you press Ctrl+C
Get-Counter -Counter "\Processor(_Total)\% Processor Time" -Continuous
# List every counter set available on this machine, alphabetically
Get-Counter -ListSet * | Sort-Object -Property CounterSetName | Format-Table CounterSetName, CounterSetType -AutoSize
# Get the exact, correctly formatted counter paths for an object,
# including its instances - useful before building a logman command
(Get-Counter -ListSet PhysicalDisk).PathsWithInstances
# Convert a finished .blg log to CSV for Excel or Power BI,
# keeping every 30th record
relog daily_trace_log.blg -cf counter_file.txt -o reduced_log.csv -t 30 -f csv
Get-Counter -ListSet * returns fewer counter sets than you expect, reopen PowerShell with Run as administrator and try again.
Common Counters Cheat Sheet
These are the counters worth adding first when you do not yet know what is wrong, along with the ranges Microsoft documents as healthy, borderline, and critical for CPU-related investigations.
| Counter | What It Tells You | Notes |
|---|---|---|
\Processor(_Total)\% Processor Time | Overall CPU utilisation across all logical processors. | 0-50% healthy, 50-80% warrants monitoring, 80-100% is critical. |
\System\Processor Queue Length | Threads waiting for CPU time. | Two or more waiting threads per processor alongside high CPU points at a real bottleneck. |
\Processor(_Total)\% Interrupt Time | Time spent servicing hardware interrupts. | Above 30% is high; above 50% is very high and often means a driver or hardware problem. |
\Processor(_Total)\% DPC Time | Time spent in deferred procedure calls. | Sustained % Processor Time above 85% combined with % DPC Time above 15% is worth investigating. |
\Process(*)\% Processor Time | Per-process CPU consumption. | Sort the samples to find which process is actually spiking, not just that the box is busy. |
\LogicalDisk(*)\% Free Space | Remaining disk space per volume. | Pairs well with a low sample rate for long-running capacity trends. |
\Memory\Available Bytes | Physical memory immediately available to processes. | A steady downward trend over days points at a leak rather than a spike. |
\Process(*)\Handle Count | Open handles per process. | A process whose handle count only ever climbs is a classic resource-leak signature. |
Troubleshooting Cheat Sheet
| Symptom | Likely Cause | Fix |
|---|---|---|
Creating a Data Collector Set fails with Access is denied |
The account is only in Performance Monitor Users, or is in Performance Log Users on Windows Server 2016+ without the batch-logon right. | Run the console or command elevated as an administrator, or grant the account’s group the Log on as a batch job right in Local Security Policy. |
| A counter path copied from another server does not resolve | Counter names are localised, so a path built in English will not resolve on a non-English system. | Run Get-Counter -ListSet * on the target machine and copy its Paths or PathsWithInstances property instead of hand-typing the path. |
| Only a handful of counter sets show up | PowerShell or perfmon is not running elevated; many counter sets are ACL-protected. | Reopen the session with Run as administrator and re-run the query. |
| The graph shows visible gaps over a multi-minute trace | Perfmon dropped samples, a documented limitation when collecting too many counters or instances at once. | Trim the counter and instance list to what you actually need, or lengthen the sample interval for long-running captures. |
| The .blg file stops growing partway through a long run | The Data Collector Set hit its -max size cap. |
Recreate the collector with a larger -max, or add -cnf so it rolls into a new file once the cap is reached. |
| Data is captured but needs to go into Excel or Power BI | The default log format is binary (.blg), not something spreadsheet tools can open directly. | Convert it after the fact with relog daily_trace_log.blg -o output.csv -f csv — no need to re-run the collection. |
Final Thoughts
Performance Monitor gets dismissed as an old MMC console because it looks like one, but the Data Collector Set underneath it is still the fastest built-in way to get hard evidence out of a Windows box without installing anything. It costs nothing extra, it works identically from the GUI or the command line, and the binary log format keeps a multi-day capture small enough to leave running.
If you are already scheduling monitoring scripts against domain controllers, a Data Collector Set fits the same slot: define it once with logman create counter, then use Task Scheduler to start and stop it on a recurring window, instead of writing a custom script to poll the same counters yourself.
logman query shows your Data Collector Set and the resulting .blg file under C:\PerfLogs\Admin is growing, it is capturing. Convert it with relog when you are ready to read it.
A natural follow-up is Event Trace Data collectors — the other half of what a Data Collector Set can hold, used for capturing provider-level ETW traces rather than periodic counter samples.