Events
17 Mar, 21 - 21 Mar, 10
Join the meetup series to build scalable AI solutions based on real-world use cases with fellow developers and experts.
Register nowThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
This article applies to: ✔️ dotnet-counters
version 3.0.47001 and later versions.
Counters can be read from applications running .NET 5 or later.
There are two ways to download and install dotnet-counters
:
dotnet global tool:
To install the latest release version of the dotnet-counters
NuGet package, use the dotnet tool install command:
dotnet tool install --global dotnet-counters
Direct download:
Download the tool executable that matches your platform:
Note
To use dotnet-counters
on an x86 app, you need a corresponding x86 version of the tool.
dotnet-counters [-h|--help] [--version] <command>
dotnet-counters
is a performance monitoring tool for ad-hoc health monitoring and first-level performance investigation. It can observe performance counter values that are published via the EventCounter API or the Meter API. For example, you can quickly monitor things like the CPU usage or the rate of exceptions being thrown in your .NET Core application to see if there's anything suspicious before diving into more serious performance investigation using PerfView
or dotnet-trace
.
--version
Displays the version of the dotnet-counters utility.
-h|--help
Shows command-line help.
Periodically collect selected counter values and export them into a specified file format for post-processing.
dotnet-counters collect [-h|--help] [-p|--process-id] [-n|--name] [--diagnostic-port] [--refresh-interval] [--counters <COUNTERS>] [--format] [-o|--output] [-- <command>]
-p|--process-id <PID>
The ID of the process to collect counter data from.
-n|--name <name>
The name of the process to collect counter data from.
--diagnostic-port
The name of the diagnostic port to create. See using diagnostic port for how to use this option to start monitoring counters from app startup.
--refresh-interval <SECONDS>
The number of seconds to delay between updating the displayed counters
--counters <COUNTERS>
A comma-separated list of counters. Counters can be specified provider_name[:counter_name]
. If the provider_name
is used without a qualifying list of counters, then all counters from the provider are shown. To discover provider and counter names, use the dotnet-counters list command. For EventCounters, provider_name
is the name of the EventSource and for Meters, provider_name
is the name of the Meter.
--format <csv|json>
The format to be exported. Currently available: csv, json.
-o|--output <output>
The name of the output file.
-- <command>
After the collection configuration parameters, the user can append --
followed by a command to start a .NET application. dotnet-counters
will launch a process with the provided command and collect the requested metrics. This is often useful to collect metrics for the application's startup path and can be used to diagnose or monitor issues that happen early before or shortly after the main entrypoint.
Note
Using this option monitors the first .NET process that communicates back to the tool, which means if your command launches multiple .NET applications, it will only collect the first app. Therefore, it is recommended you use this option on self-contained applications, or using the dotnet exec <app.dll>
option.
Note
Launching a .NET executable via dotnet-counters will redirect its input/output and you won't be able to interact with its stdin/stdout. Exiting the tool via CTRL+C or SIGTERM will safely end both the tool and the child process. If the child process exits before the tool, the tool will exit as well. If you need to use stdin/stdout, you can use the --diagnostic-port
option. See Using diagnostic port for more information.
Note
On Linux and macOS, this command expects the target application and dotnet-counters
to share the same TMPDIR
environment variable. Otherwise, the command will time out.
Note
To collect metrics using dotnet-counters
, it needs to be run as the same user as the user running target process or as root. Otherwise, the tool will fail to establish a connection with the target process.
Collect all counters at a refresh interval of 3 seconds and generate a csv as output:
> dotnet-counters collect --process-id 1902 --refresh-interval 3 --format csv
--counters is unspecified. Monitoring System.Runtime counters by default.
Starting a counter session. Press Q to quit.
Start dotnet mvc.dll
as a child process and start collecting runtime counters and ASP.NET Core Hosting counters from startup and save it as a JSON output:
> dotnet-counters collect --format json --counters System.Runtime,Microsoft.AspNetCore.Hosting -- dotnet mvc.dll
Starting a counter session. Press Q to quit.
File saved to counter.json
Displays a list of counter names and descriptions, grouped by provider.
dotnet-counters list [-h|--help]
> dotnet-counters list
Showing well-known counters only. Specific processes may support additional counters.
System.Runtime
cpu-usage Amount of time the process has utilized the CPU (ms)
working-set Amount of working set used by the process (MB)
gc-heap-size Total heap size reported by the GC (MB)
gen-0-gc-count Number of Gen 0 GCs per interval
gen-1-gc-count Number of Gen 1 GCs per interval
gen-2-gc-count Number of Gen 2 GCs per interval
time-in-gc % time in GC since the last GC
gen-0-size Gen 0 Heap Size
gen-1-size Gen 1 Heap Size
gen-2-size Gen 2 Heap Size
loh-size LOH Heap Size
alloc-rate Allocation Rate
assembly-count Number of Assemblies Loaded
exception-count Number of Exceptions per interval
threadpool-thread-count Number of ThreadPool Threads
monitor-lock-contention-count Monitor Lock Contention Count
threadpool-queue-length ThreadPool Work Items Queue Length
threadpool-completed-items-count ThreadPool Completed Work Items Count
active-timer-count Active Timers Count
Microsoft.AspNetCore.Hosting
requests-per-second Request rate
total-requests Total number of requests
current-requests Current number of requests
failed-requests Failed number of requests
Note
The Microsoft.AspNetCore.Hosting
counters are displayed when there are processes identified that support these counters, for example; when an ASP.NET Core application is running on the host machine.
Displays periodically refreshing values of selected counters.
dotnet-counters monitor [-h|--help] [-p|--process-id] [-n|--name] [--diagnostic-port] [--refresh-interval] [--counters] [-- <command>]
-p|--process-id <PID>
The ID of the process to be monitored.
-n|--name <name>
The name of the process to be monitored.
--diagnostic-port
The name of the diagnostic port to create. See using diagnostic port for how to use this option to start monitoring counters from app startup.
--refresh-interval <SECONDS>
The number of seconds to delay between updating the displayed counters
--counters <COUNTERS>
A comma-separated list of counters. Counters can be specified provider_name[:counter_name]
. If the provider_name
is used without a qualifying list of counters, then all counters from the provider are shown. To discover provider and counter names, use the dotnet-counters list command. For EventCounters, provider_name
is the name of the EventSource and for Meters, provider_name
is the name of the Meter.
-- <command>
After the collection configuration parameters, the user can append --
followed by a command to start a .NET application. dotnet-counters
will launch a process with the provided command and monitor the requested metrics. This is often useful to collect metrics for the application's startup path and can be used to diagnose or monitor issues that happen early before or shortly after the main entrypoint.
Note
Using this option monitors the first .NET process that communicates back to the tool, which means if your command launches multiple .NET applications, it will only collect the first app. Therefore, it is recommended you use this option on self-contained applications, or using the dotnet exec <app.dll>
option.
Note
Launching a .NET executable via dotnet-counters will redirect its input/output and you won't be able to interact with its stdin/stdout. Exiting the tool via CTRL+C or SIGTERM will safely end both the tool and the child process. If the child process exits before the tool, the tool will exit as well. If you need to use stdin/stdout, you can use the --diagnostic-port
option. See Using diagnostic port for more information.
Note
On Linux and macOS, this command expects the target application and dotnet-counters
to share the same TMPDIR
environment variable.
Note
To monitor metrics using dotnet-counters
, it needs to be run as the same user as the user running target process or as root.
Note
If you see an error message similar to the following one: [ERROR] System.ComponentModel.Win32Exception (299): A 32 bit processes cannot access modules of a 64 bit process.
, you are trying to use dotnet-counters
that has mismatched bitness against the target process. Make sure to download the correct bitness of the tool in the install link.
Monitor all counters from System.Runtime
at a refresh interval of 3 seconds:
> dotnet-counters monitor --process-id 1902 --refresh-interval 3 --counters System.Runtime
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate (B / 1 sec) 5,376
CPU Usage (%) 0
Exception Count (Count / 1 sec) 0
GC Fragmentation (%) 48.467
GC Heap Size (MB) 0
Gen 0 GC Count (Count / 1 sec) 1
Gen 0 Size (B) 24
Gen 1 GC Count (Count / 1 sec) 1
Gen 1 Size (B) 24
Gen 2 GC Count (Count / 1 sec) 1
Gen 2 Size (B) 272,000
IL Bytes Jitted (B) 19,449
LOH Size (B) 19,640
Monitor Lock Contention Count (Count / 1 sec) 0
Number of Active Timers 0
Number of Assemblies Loaded 7
Number of Methods Jitted 166
POH (Pinned Object Heap) Size (B) 24
ThreadPool Completed Work Item Count (Count / 1 sec) 0
ThreadPool Queue Length 0
ThreadPool Thread Count 2
Working Set (MB) 19
Monitor just CPU usage and GC heap size from System.Runtime
:
> dotnet-counters monitor --process-id 1902 --counters System.Runtime[cpu-usage,gc-heap-size]
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
CPU Usage (%) 24
GC Heap Size (MB) 811
Monitor EventCounter
values from user-defined EventSource
. For more information, see Tutorial: Measure performance using EventCounters in .NET Core.
> dotnet-counters monitor --process-id 1902 --counters Samples-EventCounterDemos-Minimal
Press p to pause, r to resume, q to quit.
request 100
View all well-known counters that are available in dotnet-counters
:
> dotnet-counters list
Showing well-known counters for .NET (Core) version 3.1 only. Specific processes may support additional counters.
System.Runtime
cpu-usage The percent of process' CPU usage relative to all of the system CPU resources [0-100]
working-set Amount of working set used by the process (MB)
gc-heap-size Total heap size reported by the GC (MB)
gen-0-gc-count Number of Gen 0 GCs between update intervals
gen-1-gc-count Number of Gen 1 GCs between update intervals
gen-2-gc-count Number of Gen 2 GCs between update intervals
time-in-gc % time in GC since the last GC
gen-0-size Gen 0 Heap Size
gen-1-size Gen 1 Heap Size
gen-2-size Gen 2 Heap Size
loh-size LOH Size
alloc-rate Number of bytes allocated in the managed heap between update intervals
assembly-count Number of Assemblies Loaded
exception-count Number of Exceptions / sec
threadpool-thread-count Number of ThreadPool Threads
monitor-lock-contention-count Number of times there were contention when trying to take the monitor lock between update intervals
threadpool-queue-length ThreadPool Work Items Queue Length
threadpool-completed-items-count ThreadPool Completed Work Items Count
active-timer-count Number of timers that are currently active
Microsoft.AspNetCore.Hosting
requests-per-second Number of requests between update intervals
total-requests Total number of requests
current-requests Current number of requests
failed-requests Failed number of requests
View all well-known counters that are available in dotnet-counters
for .NET 5 apps:
> dotnet-counters list --runtime-version 5.0
Showing well-known counters for .NET (Core) version 5.0 only. Specific processes may support additional counters.
System.Runtime
cpu-usage The percent of process' CPU usage relative to all of the system CPU resources [0-100]
working-set Amount of working set used by the process (MB)
gc-heap-size Total heap size reported by the GC (MB)
gen-0-gc-count Number of Gen 0 GCs between update intervals
gen-1-gc-count Number of Gen 1 GCs between update intervals
gen-2-gc-count Number of Gen 2 GCs between update intervals
time-in-gc % time in GC since the last GC
gen-0-size Gen 0 Heap Size
gen-1-size Gen 1 Heap Size
gen-2-size Gen 2 Heap Size
loh-size LOH Size
poh-size POH (Pinned Object Heap) Size
alloc-rate Number of bytes allocated in the managed heap between update intervals
gc-fragmentation GC Heap Fragmentation
assembly-count Number of Assemblies Loaded
exception-count Number of Exceptions / sec
threadpool-thread-count Number of ThreadPool Threads
monitor-lock-contention-count Number of times there were contention when trying to take the monitor lock between update intervals
threadpool-queue-length ThreadPool Work Items Queue Length
threadpool-completed-items-count ThreadPool Completed Work Items Count
active-timer-count Number of timers that are currently active
il-bytes-jitted Total IL bytes jitted
methods-jitted-count Number of methods jitted
Microsoft.AspNetCore.Hosting
requests-per-second Number of requests between update intervals
total-requests Total number of requests
current-requests Current number of requests
failed-requests Failed number of requests
Microsoft-AspNetCore-Server-Kestrel
connections-per-second Number of connections between update intervals
total-connections Total Connections
tls-handshakes-per-second Number of TLS Handshakes made between update intervals
total-tls-handshakes Total number of TLS handshakes made
current-tls-handshakes Number of currently active TLS handshakes
failed-tls-handshakes Total number of failed TLS handshakes
current-connections Number of current connections
connection-queue-length Length of Kestrel Connection Queue
request-queue-length Length total HTTP request queue
System.Net.Http
requests-started Total Requests Started
requests-started-rate Number of Requests Started between update intervals
requests-aborted Total Requests Aborted
requests-aborted-rate Number of Requests Aborted between update intervals
current-requests Current Requests
Launch my-aspnet-server.exe
and monitor the # of assemblies loaded from its startup:
> dotnet-counters monitor --counters System.Runtime[assembly-count] -- my-aspnet-server.exe
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
Number of Assemblies Loaded 24
Launch my-aspnet-server.exe
with arg1
and arg2
as command-line arguments and monitor its working set and GC heap size from its startup:
> dotnet-counters monitor --counters System.Runtime[working-set,gc-heap-size] -- my-aspnet-server.exe arg1 arg2
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
GC Heap Size (MB) 39
Working Set (MB) 59
Lists the dotnet processes that can be monitored by dotnet-counters
.
dotnet-counters
version 6.0.320703 and later, also display the command-line arguments that each process was started with, if available.
dotnet-counters ps [-h|--help]
Suppose you start a long-running app using the command dotnet run --configuration Release
. In another window, you run the dotnet-counters ps
command. The output you'll see is as follows. The command-line arguments, if any, are shown in dotnet-counters
version 6.0.320703 and later.
> dotnet-counters ps
21932 dotnet C:\Program Files\dotnet\dotnet.exe run --configuration Release
36656 dotnet C:\Program Files\dotnet\dotnet.exe
Diagnostic port is a runtime feature that allows you to start monitoring or collecting counters from app startup. To do this using dotnet-counters
, you can either use dotnet-counters <collect|monitor> -- <command>
as described in the examples above, or use the --diagnostic-port
option.
Using dotnet-counters <collect|monitor> -- <command>
to launch the application as a child process is the simplest way to quickly monitor it from its startup.
However, when you want to gain a finer control over the lifetime of the app being monitored (for example, monitor the app for the first 10 minutes only and continue executing) or if you need to interact with the app using the CLI, using --diagnostic-port
option allows you to control both the target app being monitored and dotnet-counters
.
The command below makes dotnet-counters create a diagnostics socket named myport.sock
and wait for a connection.
.NET CLI
dotnet-counters collect --diagnostic-port myport.sock
Output:
OutputWaiting for connection on myport.sock Start an application with the following environment variable: DOTNET_DiagnosticPorts=/home/user/myport.sock
In a separate console, launch the target application with the environment variable DOTNET_DiagnosticPorts
set to the value in the dotnet-counters
output.
Consoleexport DOTNET_DiagnosticPorts=/home/user/myport.sock ./my-dotnet-app arg1 arg2
This should then enable dotnet-counters
to start collecting counters on my-dotnet-app
:
OutputWaiting for connection on myport.sock Start an application with the following environment variable: DOTNET_DiagnosticPorts=myport.sock Starting a counter session. Press Q to quit.
Important
Launching your app with dotnet run
can be problematic because the dotnet CLI may spawn many child processes that are not your app and they can connect to dotnet-counters
before your app, leaving your app to be suspended at run time. It is recommended you directly use a self-contained version of the app or use dotnet exec
to launch the application.
.NET feedback
.NET is an open source project. Select a link to provide feedback:
Events
17 Mar, 21 - 21 Mar, 10
Join the meetup series to build scalable AI solutions based on real-world use cases with fellow developers and experts.
Register now