Skip to content

Commit ff30d36

Browse files
noahfalkgewarren
andauthored
Migration guidance for Windows Performance Counters (#45943)
* Migration guidance for Windows Performance Counters Adding some info to help folks on Windows .NET Framework find suitable replacement metrics for monitoring .NET Core. * Apply suggestions from code review Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --------- Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com>
1 parent 3373a85 commit ff30d36

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
title: Migrate from .NET Windows Performance Counters to .NET Core metrics
3+
description: Learn how to migrate from .NET Framework Windows Performance Counters to .NET Core/NET 5+ metrics using EventCounters and Meters.
4+
ms.date: 04/27/2025
5+
---
6+
7+
# Migrate from .NET Framework Windows Performance Counters to .NET metrics
8+
9+
.NET Framework applications, which only run on Windows, can use Windows Performance Counters to monitor application health and performance. However, in .NET Core and later versions, the platform provides [cross-platform alternatives](compare-metric-apis.md) through the [EventCounters](./event-counters.md) and [System.Diagnostics.Metrics](./metrics.md) APIs.
10+
11+
This article provides guidance on migrating from Windows Performance Counters to the newer metrics systems available in modern .NET versions.
12+
13+
## A short history of .NET metrics
14+
15+
.NET applications can be monitored using different mechanisms depending on the .NET version and platform:
16+
17+
- **.NET Framework**: Primarily uses Windows Performance Counters (Windows only)
18+
- **.NET Core 3.0-3.1, .NET 5+**: Introduced EventCounters (cross-platform) and built-in [runtime metrics](./available-counters.md#systemruntime-counters), [networking metrics](./available-counters.md#systemnethttp-counters), and [ASP.NET metrics](./available-counters.md#microsoft-aspnetcore-server-kestrel-counters) using these APIs
19+
- **.NET 6+**: Added System.Diagnostics.Metrics API (cross-platform, OpenTelemetry compatible)
20+
- **.NET 8+**: Added built-in [networking metrics](./built-in-metrics-system-net.md) and [ASP.NET metrics](/aspnet/core/log-mon/metrics/built-in) using the new System.Diagnostics.Metrics API
21+
- **.NET 9+**: Added built-in [runtime metrics](./built-in-metrics-runtime.md) using the new System.Diagnostics.Metrics API
22+
23+
The newer metrics systems offer several advantages:
24+
25+
- **Cross-platform operation**: Works on Windows, Linux, macOS
26+
- **Container-friendly**: Works in containerized environments
27+
- **Modern tooling**: Integrates with OpenTelemetry and observability platforms
28+
- **Supports xcopy install**: No additional installation steps or privileges are required
29+
30+
For more information, see the [Metrics API comparison](compare-metric-apis.md).
31+
32+
## Collect metrics in modern .NET applications
33+
34+
To collect and analyze metrics, see the [System.Diagnostics.Metrics](./metrics-collection.md) and [EventCounters](./event-counters.md) guides.
35+
36+
## Map common Windows Performance Counters to modern metrics
37+
38+
If the monitoring system for your .NET Framework application uses runtime-provided Windows Performance Counters, you'll need to select alternative [EventCounters](./event-counters.md)
39+
or [System.Diagnostics.Metrics](./metrics.md)-based metrics instead. The following tables show alternatives for many common counters. Not all .NET Framework counters have been ported to new alternatives.
40+
In some cases, infrequently used counters were discontinued, and in other cases, implementation changes in the platform have made certain counters irrelevant.
41+
42+
### Memory counters
43+
44+
| Windows Performance Counter | EventCounter equivalent | Metrics API equivalent |
45+
|----------------------------|--------------------------|------------------------|
46+
| `.NET CLR Memory\# Bytes in all Heaps` | `System.Runtime\GC Heap Size` (`gc-heap-size`) | `System.Runtime\dotnet.gc.last_collection.heap.size` |
47+
| `.NET CLR Memory\# Gen 0 Collections` | `System.Runtime\Gen 0 GC Count` (`gen-0-gc-count`) | `System.Runtime\dotnet.gc.collections` with attribute `gc.heap.generation=gen0` |
48+
| `.NET CLR Memory\# Gen 1 Collections` | `System.Runtime\Gen 1 GC Count` (`gen-1-gc-count`) | `System.Runtime\dotnet.gc.collections` with attribute `gc.heap.generation=gen1` |
49+
| `.NET CLR Memory\# Gen 2 Collections` | `System.Runtime\Gen 2 GC Count` (`gen-2-gc-count`) | `System.Runtime\dotnet.gc.collections` with attribute `gc.heap.generation=gen2` |
50+
| `.NET CLR Memory\% Time in GC` | `System.Runtime\% Time in GC since last GC` (`time-in-gc`) | `System.Runtime\dotnet.gc.pause.time` (calculate as percentage of total time) |
51+
| `.NET CLR Memory\# Total committed Bytes` | None | `System.Runtime\dotnet.gc.last_collection.memory.committed_size` |
52+
| `.NET CLR Memory\Large Object Heap Size` | `System.Runtime\LOH Size` (`loh-size`) | `System.Runtime\dotnet.gc.last_collection.heap.size` with attribute `gc.heap.generation=loh` |
53+
| `.NET CLR Memory\Allocated Bytes/sec` | `System.Runtime\Allocation Rate` (`alloc-rate`) | Calculate rate from `System.Runtime\dotnet.gc.heap.total_allocated` |
54+
55+
> [!NOTE]
56+
> `dotnet.gc.pause.time` allows an improved calculation that avoids some undesirable behavior in the older `% Time in GC` metric. `% Time in GC` computed
57+
> 100 * `pause_time_in_most_recent_GC` / `time_between_most_recent_two_GCs`. In some cases two GCs would occur very close together producing a high value
58+
> based on a tiny non-representative portion of the overall time interval. `gc.heap.pause.time` accumulates the total time the GC has paused application threads
59+
> so far in a process, which allows computing the GC pause time during any measured time interval. This is a truer measurement of GC overhead, but the change in calculation
60+
> means the metrics might not match even when the underlying GC behavior is unchanged.
61+
62+
### JIT and Loading counters
63+
64+
| Windows Performance Counter | EventCounter equivalent | Metrics API equivalent |
65+
|----------------------------|--------------------------|------------------------|
66+
| `.NET CLR Jit\# of Methods Jitted` | `System.Runtime\Methods Jitted Count` (`methods-jitted-count`) | `System.Runtime\dotnet.jit.compiled_methods` |
67+
| `.NET CLR Jit\IL Bytes Jitted` | `System.Runtime\IL Bytes Jitted` (`il-bytes-jitted`) | `System.Runtime\dotnet.jit.compiled_il.size` |
68+
| `.NET CLR Loading\Current Assemblies` | `System.Runtime\Number of Assemblies Loaded` (`assembly-count`) | `System.Runtime\dotnet.assembly.count` |
69+
| `.NET CLR Jit\Total # of IL Bytes Jitted` | `System.Runtime\IL Bytes Jitted` (`il-bytes-jitted`) | `System.Runtime\dotnet.jit.compiled_il.size` |
70+
71+
### Threading counters
72+
73+
| Windows Performance Counter | EventCounter equivalent | Metrics API equivalent |
74+
|----------------------------|--------------------------|------------------------|
75+
| `.NET CLR LocksAndThreads\Current Queue Length` | `System.Runtime\ThreadPool Queue Length` (`threadpool-queue-length`) | `System.Runtime\dotnet.thread_pool.queue.length` |
76+
| `.NET CLR LocksAndThreads\Contention Rate / sec` | `System.Runtime\Monitor Lock Contention Count` (`monitor-lock-contention-count`) | Calculate rate from `System.Runtime\dotnet.monitor.lock_contentions` |
77+
78+
### Exceptions counters
79+
80+
| Windows Performance Counter | EventCounter equivalent | Metrics API equivalent |
81+
|----------------------------|--------------------------|------------------------|
82+
| `.NET CLR Exceptions\# of Exceps Thrown / sec` | `System.Runtime\Exception Count` (`exception-count`) | Calculate rate from `System.Runtime\dotnet.exceptions` |
83+
| `.NET CLR Exceptions\# of Exceps Thrown` | None | `System.Runtime\dotnet.exceptions` |
84+
85+
### Socket networking counters
86+
87+
| Windows Performance Counter | EventCounter equivalent | Metrics API equivalent |
88+
|----------------------------|--------------------------|------------------------|
89+
| `.NET CLR Networking\Bytes Received` | `System.Net.Sockets\Bytes Received` (`bytes-received`) | None |
90+
| `.NET CLR Networking\Bytes Sent` | `System.Net.Sockets\Bytes Sent` (`bytes-sent`) | None |
91+
| `.NET CLR Networking\Connections Established` | `System.Net.Sockets\Outgoing Connections Established` (`outgoing-connections-established`) | None |
92+
| `.NET CLR Networking\Datagrams Received` | `System.Net.Sockets\Datagrams Received` (`datagrams-received`) | None |
93+
| `.NET CLR Networking\Datagrams Sent` | `System.Net.Sockets\Datagrams Sent` (`datagrams-sent`) | None |
94+
95+
### DNS networking counters
96+
97+
| Windows Performance Counter | EventCounter equivalent | Metrics API equivalent |
98+
|----------------------------|--------------------------|------------------------|
99+
| `.NET CLR Networking\DNS Lookups` | `System.Net.NameResolution\DNS Lookups Requested` (`dns-lookups-requested`) | Sum the histogram buckets in `System.Net.NameResolution\dns.lookup.duration` |
100+
| `.NET CLR Networking\DNS Resolution Time` | `System.Net.NameResolution\Average DNS Lookup Duration` (`dns-lookups-duration`) | `System.Net.NameResolution\dns.lookup.duration` |
101+
102+
### HttpWebRequest counters
103+
104+
`HttpWebRequest` has been superseded by <xref:System.Net.Http.HttpClient>. To learn what metrics are built-in, see the HttpClient [EventCounters](./available-counters.md#systemnethttp-counters) and [System.Diagnostics.Metrics](./built-in-metrics-system-net.md#systemnethttp).
105+
106+
### ASP.NET counters
107+
108+
ASP.NET has changed dramatically between .NET Framework and .NET Core. Many counters are obsolete or are measured differently than in the past. To learn what metrics are built-in, see the ASP.NET [EventCounters](./available-counters.md#microsoftaspnetcorehosting-counters) and [System.Diagnostics.Metrics](/aspnet/core/log-mon/metrics/built-in).
109+
110+
## Next steps
111+
112+
- Learn more about [EventCounters in .NET](./event-counters.md)
113+
- Explore the [System.Diagnostics.Metrics API](./metrics.md)
114+
- Understand how to [collect metrics](./metrics-collection.md)
115+
- Review [well-known EventCounters](./available-counters.md) and [built-in metrics](./built-in-metrics.md)

docs/navigate/tools-diagnostics/toc.yml

+2
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,8 @@ items:
419419
href: ../../core/diagnostics/event-counter-perf.md
420420
- name: Compare metric APIs
421421
href: ../../core/diagnostics/compare-metric-apis.md
422+
- name: Migrate from Windows Performance Counters
423+
href: ../../core/diagnostics/migrate-from-windows-performance-counters.md
422424
- name: Distributed tracing
423425
items:
424426
- name: Overview

0 commit comments

Comments
 (0)