{"id":54155,"date":"2025-11-25T03:25:21","date_gmt":"2025-11-25T03:25:21","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=54155"},"modified":"2025-11-25T03:48:42","modified_gmt":"2025-11-25T03:48:42","slug":"the-ultimate-net-counters-tutorial","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/the-ultimate-net-counters-tutorial\/","title":{"rendered":"dotnet-counters: The Ultimate .NET Counters Tutorial"},"content":{"rendered":"\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\"><em>Real-Time Diagnostics for .NET Runtime, ASP.NET Core, EF Core, Networking &amp; More<\/em><\/h1>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">1. <strong>Introduction to dotnet-counters<\/strong><\/h1>\n\n\n\n<p><strong>dotnet-counters<\/strong> is a <strong>cross-platform performance monitoring tool<\/strong> for .NET applications. It provides <strong>real-time metrics<\/strong> about the .NET runtime and your application without requiring any code changes or stopping the app.<\/p>\n\n\n\n<p>It is part of the <strong>.NET Diagnostic Tools suite<\/strong>.<\/p>\n\n\n\n<p>It enables developers, performance engineers, and SREs to understand:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CPU usage<\/li>\n\n\n\n<li>Memory allocations<\/li>\n\n\n\n<li>GC behavior<\/li>\n\n\n\n<li>ThreadPool health<\/li>\n\n\n\n<li>ASP.NET Core traffic<\/li>\n\n\n\n<li>Kestrel server load<\/li>\n\n\n\n<li>System.Net outbound connections<\/li>\n\n\n\n<li>EF Core queries &amp; DB activity<\/li>\n\n\n\n<li>Lock contention<\/li>\n\n\n\n<li>Process working set<\/li>\n\n\n\n<li>Request rates<\/li>\n\n\n\n<li>Connection counts<\/li>\n\n\n\n<li>And MUCH more<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">2. <strong>What is dotnet-counters? (Definition)<\/strong><\/h1>\n\n\n\n<p><code>dotnet-counters<\/code> is a lightweight CLI utility that <strong>subscribes to runtime performance metrics<\/strong> exposed by:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>A. EventCounters<\/strong> (classic counters)<\/h3>\n\n\n\n<p>Used by:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>System.Runtime<\/li>\n\n\n\n<li>Microsoft.AspNetCore.Hosting<\/li>\n\n\n\n<li>Microsoft-AspNetCore-Server-Kestrel<\/li>\n\n\n\n<li>Microsoft.AspNetCore.Http.Connections<\/li>\n\n\n\n<li>System.Net.Http<\/li>\n\n\n\n<li>Microsoft.EntityFrameworkCore (legacy events)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>B. System.Diagnostics.Metrics<\/strong> (new .NET metrics API)<\/h3>\n\n\n\n<p>Used by:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ASP.NET Core built-in metrics<\/li>\n\n\n\n<li>EF Core built-in metrics<\/li>\n\n\n\n<li>System.Net<\/li>\n\n\n\n<li>.NET Runtime metrics<\/li>\n\n\n\n<li>Custom application metrics<\/li>\n<\/ul>\n\n\n\n<p>The tool displays these counters <strong>live<\/strong> or <strong>records them<\/strong> to a file.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">3. <strong>Why dotnet-counters exists (Purpose)<\/strong><\/h1>\n\n\n\n<p>Before dotnet-counters, diagnosing .NET performance issues required:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Attaching heavyweight profilers<\/li>\n\n\n\n<li>Installing Visual Studio Diagnostics<\/li>\n\n\n\n<li>Using Windows-only tools<\/li>\n\n\n\n<li>Waiting for dumps or logs<\/li>\n<\/ul>\n\n\n\n<p>These methods were <strong>slow<\/strong>, <strong>disruptive<\/strong>, and <strong>risky for production<\/strong>.<\/p>\n\n\n\n<p>Modern .NET apps run on:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Linux containers<\/li>\n\n\n\n<li>Kubernetes<\/li>\n\n\n\n<li>Cloud VMs<\/li>\n\n\n\n<li>Azure App Service<\/li>\n\n\n\n<li>AWS ECS\/EKS<\/li>\n\n\n\n<li>Docker<\/li>\n<\/ul>\n\n\n\n<p>What developers need is a <strong>safe, fast, cross-platform<\/strong> way to monitor live performance.<\/p>\n\n\n\n<p><strong>dotnet-counters solves this.<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">4. <strong>When to Use dotnet-counters<\/strong><\/h1>\n\n\n\n<p>Use dotnet-counters when you need:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 Live performance monitoring<\/h3>\n\n\n\n<p>\u2714 Realtime GC insight<br>\u2714 See allocations immediately<br>\u2714 Detect memory leaks<br>\u2714 Detect CPU spikes<br>\u2714 View RPS (requests\/sec)<br>\u2714 Investigate latency &amp; saturation<br>\u2714 Observe EF Core query load<br>\u2714 Analyze Kestrel traffic<br>\u2714 Identify contention issues<br>\u2714 Understand warm-up behavior<br>\u2714 Inspect ThreadPool starvation<br>\u2714 Debug production without restarts<br>\u2714 Monitor cloud workloads<\/p>\n\n\n\n<p>You use it in:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Local development<\/strong><\/li>\n\n\n\n<li><strong>Performance testing<\/strong><\/li>\n\n\n\n<li><strong>Load testing (JMeter, K6, Locust)<\/strong><\/li>\n\n\n\n<li><strong>Staging \/ UAT<\/strong><\/li>\n\n\n\n<li><strong>Production (safe)<\/strong><\/li>\n\n\n\n<li><strong>Kubernetes clusters<\/strong><\/li>\n\n\n\n<li><strong>Docker containers<\/strong><\/li>\n\n\n\n<li><strong>Azure\/AWS troubleshooting<\/strong><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">5. <strong>Installing dotnet-counters<\/strong><\/h1>\n\n\n\n<p>It&#8217;s included with the .NET SDK.<\/p>\n\n\n\n<p>Check version:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">dotnet-counters --version\n<\/code><\/span><\/pre>\n\n\n<p>If not installed:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">dotnet tool install -g dotnet-counters\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">6. <strong>dotnet-counters Commands Overview<\/strong><\/h1>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">dotnet-counters\n<\/code><\/span><\/pre>\n\n\n<p>You get:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Command<\/th><th>Purpose<\/th><\/tr><\/thead><tbody><tr><td><strong>monitor<\/strong><\/td><td>LIVE real-time metrics<\/td><\/tr><tr><td><strong>collect<\/strong><\/td><td>Record metrics to a file (offline analysis)<\/td><\/tr><tr><td><strong>list<\/strong><\/td><td>Show available counter providers<\/td><\/tr><tr><td><strong>ps<\/strong><\/td><td>List running .NET processes<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">7. <strong>Listing .NET Processes<\/strong><\/h1>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">dotnet-counters ps\n<\/code><\/span><\/pre>\n\n\n<p>Shows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">1234  <span class=\"hljs-selector-tag\">MyApp<\/span><span class=\"hljs-selector-class\">.Web<\/span>\n5678  <span class=\"hljs-selector-tag\">WorkerService<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">8. <strong>Showing Available Counters<\/strong><\/h1>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">dotnet-counters <span class=\"hljs-keyword\">list<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now returns a pointer to documentation:<\/p>\n\n\n\n<p>\u27a1 <a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters\" target=\"_blank\" rel=\"noopener\">https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters<\/a><br>(This is your main EventCounters reference.)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">9. <strong>Monitoring an App in Real Time (monitor)<\/strong><\/h1>\n\n\n\n<p>Basic usage:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">dotnet-counters monitor -p <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PID<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>With specific providers:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">dotnet-counters<\/span> <span class=\"hljs-selector-tag\">monitor<\/span> <span class=\"hljs-selector-tag\">-p<\/span> &lt;<span class=\"hljs-selector-tag\">PID<\/span>&gt; <span class=\"hljs-selector-tag\">System<\/span><span class=\"hljs-selector-class\">.Runtime<\/span> <span class=\"hljs-selector-tag\">Microsoft<\/span><span class=\"hljs-selector-class\">.AspNetCore<\/span><span class=\"hljs-selector-class\">.Hosting<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Your full example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">dotnet-counters<\/span> <span class=\"hljs-selector-tag\">monitor<\/span> <span class=\"hljs-selector-tag\">-p<\/span> 30420 <span class=\"hljs-selector-tag\">System<\/span><span class=\"hljs-selector-class\">.Runtime<\/span> <span class=\"hljs-selector-tag\">Microsoft<\/span><span class=\"hljs-selector-class\">.AspNetCore<\/span><span class=\"hljs-selector-class\">.Hosting<\/span> <span class=\"hljs-selector-tag\">Microsoft-AspNetCore-Server-Kestrel<\/span> <span class=\"hljs-selector-tag\">Microsoft<\/span><span class=\"hljs-selector-class\">.AspNetCore<\/span><span class=\"hljs-selector-class\">.Http<\/span><span class=\"hljs-selector-class\">.Connections<\/span> <span class=\"hljs-selector-tag\">System<\/span><span class=\"hljs-selector-class\">.Net<\/span><span class=\"hljs-selector-class\">.Http<\/span> <span class=\"hljs-selector-tag\">Microsoft<\/span><span class=\"hljs-selector-class\">.EntityFrameworkCore<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Press:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>p<\/strong> \u2192 pause<\/li>\n\n\n\n<li><strong>r<\/strong> \u2192 resume<\/li>\n\n\n\n<li><strong>q<\/strong> \u2192 quit<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">10. <strong>Recording Metrics to a File (collect)<\/strong><\/h1>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">dotnet-counters collect -p <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PID<\/span>&gt;<\/span> -o output.json\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Useful for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Long-running captures<\/li>\n\n\n\n<li>Production debugging<\/li>\n\n\n\n<li>Attaching to Jira tickets<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">11. <strong>Providers &amp; Metrics (Deep Dive)<\/strong><\/h1>\n\n\n\n<p>The BIG section \u2014 covers <strong>EVERY provider<\/strong> you need.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11.1 <strong>System.Runtime Counters<\/strong><\/h2>\n\n\n\n<p>Source:<br><a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters\" target=\"_blank\" rel=\"noopener\">https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Key Metrics:<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Metric<\/th><th>Meaning<\/th><\/tr><\/thead><tbody><tr><td>CPU Usage (%)<\/td><td>CPU used by the process<\/td><\/tr><tr><td>Allocation Rate<\/td><td>Bytes allocated\/sec<\/td><\/tr><tr><td>GC Heap Size<\/td><td>Managed heap usage<\/td><\/tr><tr><td>GC Committed Bytes<\/td><td>Memory reserved by GC<\/td><\/tr><tr><td>% Time in GC<\/td><td>How much the app is paused for GC<\/td><\/tr><tr><td>Time paused by GC<\/td><td>Actual GC stop-the-world pause time<\/td><\/tr><tr><td>Gen 0\/1\/2 GC Count<\/td><td>Garbage collections<\/td><\/tr><tr><td>Working Set<\/td><td>Total memory consumption<\/td><\/tr><tr><td>Exception Count<\/td><td>Throw rate<\/td><\/tr><tr><td>ThreadPool Thread Count<\/td><td>Current pool size<\/td><\/tr><tr><td>ThreadPool Queue Length<\/td><td>Pending work items<\/td><\/tr><tr><td>Lock Contention Count<\/td><td>Locking issues<\/td><\/tr><tr><td>JIT Bytes<\/td><td>IL compiled<\/td><\/tr><tr><td>Methods Jitted<\/td><td>Total jitted methods<\/td><\/tr><tr><td>Active Timers<\/td><td>Timers currently alive<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><strong>This is the heart of your diagnostics.<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11.2 <strong>ASP.NET Core Hosting Metrics<\/strong><\/h2>\n\n\n\n<p>Source:<br><a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/log-mon\/metrics\/built-in\" target=\"_blank\" rel=\"noopener\">https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/log-mon\/metrics\/built-in<\/a><\/p>\n\n\n\n<p>Counters include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>requests-per-second<\/code><\/li>\n\n\n\n<li><code>current-requests<\/code><\/li>\n\n\n\n<li><code>failed-requests<\/code><\/li>\n\n\n\n<li><code>total-requests<\/code><\/li>\n\n\n\n<li><code>request-duration<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11.3 <strong>Kestrel Server Metrics<\/strong><\/h2>\n\n\n\n<p>Source:<br><a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters\" target=\"_blank\" rel=\"noopener\">https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters<\/a><\/p>\n\n\n\n<p>Includes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>current-connections<\/code><\/li>\n\n\n\n<li><code>tls-handshake-failures<\/code><\/li>\n\n\n\n<li><code>connection-queue-length<\/code><\/li>\n\n\n\n<li><code>request-queue-length<\/code><\/li>\n\n\n\n<li><code>connections-per-second<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11.4 <strong>ASP.NET Core HTTP Connections (SignalR)<\/strong><\/h2>\n\n\n\n<p>Counters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>current-connections<\/code><\/li>\n\n\n\n<li><code>connections-started<\/code><\/li>\n\n\n\n<li><code>connections-stopped<\/code><\/li>\n\n\n\n<li><code>connections-timed-out<\/code><\/li>\n\n\n\n<li><code>connection-duration<\/code><\/li>\n<\/ul>\n\n\n\n<p>Useful for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>WebSockets<\/li>\n\n\n\n<li>SignalR<\/li>\n\n\n\n<li>Real-time APIs<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11.5 <strong>System.Net.Http<\/strong><\/h2>\n\n\n\n<p>Source:<br><a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters\" target=\"_blank\" rel=\"noopener\">https:\/\/learn.microsoft.com\/dotnet\/core\/diagnostics\/available-counters<\/a><\/p>\n\n\n\n<p>Counters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>requests-started<\/code><\/li>\n\n\n\n<li><code>requests-started-rate<\/code><\/li>\n\n\n\n<li><code>requests-failed<\/code><\/li>\n\n\n\n<li><code>http11-connections-current-total<\/code><\/li>\n\n\n\n<li><code>http20-streams-current-total<\/code><\/li>\n\n\n\n<li><code>http30-connections-established<\/code><\/li>\n\n\n\n<li><code>dns-lookups-duration<\/code><\/li>\n\n\n\n<li><code>sockets-queued<\/code><\/li>\n<\/ul>\n\n\n\n<p>Great for diagnosing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Slow outbound APIs<\/li>\n\n\n\n<li>Connection pooling issues<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11.6 <strong>EF Core Metrics (Modern + Legacy)<\/strong><\/h2>\n\n\n\n<p>Source:<br><a href=\"https:\/\/learn.microsoft.com\/en-us\/ef\/core\/logging-events-diagnostics\/metrics\" target=\"_blank\" rel=\"noopener\">https:\/\/learn.microsoft.com\/en-us\/ef\/core\/logging-events-diagnostics\/metrics<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">EF Core Built-in Metrics (New API)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>microsoft.entityframeworkcore.query.compilation-events<\/code><\/li>\n\n\n\n<li><code>microsoft.entityframeworkcore.commands.executed<\/code><\/li>\n\n\n\n<li><code>microsoft.entityframeworkcore.active-dbcontexts<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Legacy EventCounters compatible with dotnet-counters<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Query execution count<\/li>\n\n\n\n<li>Query execution rate<\/li>\n\n\n\n<li>DbContext count<\/li>\n\n\n\n<li>Optimistic concurrency failures<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">12. <strong>Interpreting dotnet-counters Output<\/strong><\/h1>\n\n\n\n<p>Example snapshot:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">Allocation Rate                <span class=\"hljs-number\">50<\/span>,<span class=\"hljs-number\">067<\/span>,<span class=\"hljs-number\">464<\/span> B\/sec\nGC Heap Size                  <span class=\"hljs-number\">239<\/span> MB\nWorking <span class=\"hljs-built_in\">Set<\/span>                   <span class=\"hljs-number\">491<\/span> MB\nThreadPool Completed\/<span class=\"hljs-number\">1<\/span>sec     <span class=\"hljs-number\">609<\/span>\nLock Contention Count\/sec     <span class=\"hljs-number\">2<\/span>\nTime paused by GC             <span class=\"hljs-number\">0<\/span>\nCPU Usage                     <span class=\"hljs-number\">5<\/span>%\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Interpretation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>High allocation rate \u2192 future GC pressure<\/li>\n\n\n\n<li>Large heap \u2192 memory-heavy workload<\/li>\n\n\n\n<li>Large working set \u2192 big resident memory footprint<\/li>\n\n\n\n<li>Lock contention \u2192 possible bottleneck<\/li>\n\n\n\n<li>Nonzero Gen2 size \u2192 long-lived allocations<\/li>\n\n\n\n<li>JIT activity \u2192 warm-up in progress<\/li>\n\n\n\n<li>High request rate \u2192 check RPS counters in Hosting provider<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">13. <strong>When dotnet-counters is Most Valuable<\/strong><\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udfe2 Development<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Validate memory patterns<\/li>\n\n\n\n<li>Analyze LINQ allocations<\/li>\n\n\n\n<li>Investigate EF Core inefficiencies<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udfe1 Load Testing<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>See RPS<\/li>\n\n\n\n<li>See GC stress<\/li>\n\n\n\n<li>See thread starvation<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd35 Staging\/UAT<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Compare performance baseline<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd34 Production<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Safe to use<\/li>\n\n\n\n<li>Zero-impact monitoring<\/li>\n\n\n\n<li>Perfect for Kubernetes<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">14. <strong>Performance Use Cases (Real World)<\/strong><\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 Memory Leak Detection<\/h3>\n\n\n\n<p>Watch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>GC Heap Size (keeps growing?)<\/li>\n\n\n\n<li>Gen 2 Size<\/li>\n\n\n\n<li>LOH Size<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 High CPU Investigation<\/h3>\n\n\n\n<p>Watch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CPU Usage (%)<\/li>\n\n\n\n<li>Allocation Rate<\/li>\n\n\n\n<li>JIT time<\/li>\n\n\n\n<li>Lock contention<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 GC Bottleneck<\/h3>\n\n\n\n<p>Watch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>% Time in GC<\/li>\n\n\n\n<li>Time paused by GC<\/li>\n\n\n\n<li>Gen 0\/1\/2 Count<\/li>\n\n\n\n<li>Allocation Rate<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 ThreadPool Starvation<\/h3>\n\n\n\n<p>Watch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ThreadPool Queue Length<\/li>\n\n\n\n<li>ThreadPool Completed Work Items<\/li>\n\n\n\n<li>Thread Count<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 ASP.NET Core Throughput<\/h3>\n\n\n\n<p>Watch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>RPS<\/li>\n\n\n\n<li>Failure rate<\/li>\n\n\n\n<li>Current requests<\/li>\n\n\n\n<li>Connection count<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 EF Core Problem Analysis<\/h3>\n\n\n\n<p>Watch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Queries\/sec<\/li>\n\n\n\n<li>Active DbContexts<\/li>\n\n\n\n<li>Command execution count<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">15. <strong>Advantages of dotnet-counters<\/strong><\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 Cross-platform (Windows, Linux, macOS)<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 Zero overhead (production-friendly)<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 Instant insights<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 No process restart<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 No profilers needed<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 No code changes<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 Works in Docker, Kubernetes, cloud<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 Works with all .NET apps (5\/6\/7\/8\/9+)<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca0 Supports both EventCounters and Metrics API<\/h3>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">16. <strong>Benefits<\/strong><\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfaf Rapid diagnosis<\/h3>\n\n\n\n<p>Find issues instantly (CPU, GC, memory, queries).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfaf Safe for production<\/h3>\n\n\n\n<p>Unlike profilers, does not slow down your app.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfaf Complements logs &amp; APM<\/h3>\n\n\n\n<p>Fills the gap between logs, traces, and dumps.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfaf Helps tune performance<\/h3>\n\n\n\n<p>Identify:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Excessive allocations<\/li>\n\n\n\n<li>Slow queries<\/li>\n\n\n\n<li>ThreadPool starvation<\/li>\n\n\n\n<li>High RPS behavior<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfaf Helps SREs<\/h3>\n\n\n\n<p>Useful for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Incident analysis<\/li>\n\n\n\n<li>Postmortems<\/li>\n\n\n\n<li>Capacity planning<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">17. <strong>Best Practices<\/strong><\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Always include <code>System.Runtime<\/code> <strong>first<\/strong><\/li>\n\n\n\n<li>Add more providers only as needed<\/li>\n\n\n\n<li>Use <code>collect<\/code> for long sessions<\/li>\n\n\n\n<li>Compare snapshots at:\n<ul class=\"wp-block-list\">\n<li>Idle<\/li>\n\n\n\n<li>Under load<\/li>\n\n\n\n<li>After runaway memory events<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Capture before &amp; after deployment<\/li>\n\n\n\n<li>Combine with:\n<ul class=\"wp-block-list\">\n<li><code>dotnet-trace<\/code><\/li>\n\n\n\n<li><code>dotnet-gcdump<\/code><\/li>\n\n\n\n<li><code>dotnet-dump<\/code><\/li>\n\n\n\n<li>Application logs<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">18. <strong>Full Example Command Set<\/strong><\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">Monitor everything:<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">dotnet-counters<\/span> <span class=\"hljs-selector-tag\">monitor<\/span> <span class=\"hljs-selector-tag\">-p<\/span> &lt;<span class=\"hljs-selector-tag\">PID<\/span>&gt; \\\n  <span class=\"hljs-selector-tag\">System<\/span><span class=\"hljs-selector-class\">.Runtime<\/span> \\\n  <span class=\"hljs-selector-tag\">Microsoft<\/span><span class=\"hljs-selector-class\">.AspNetCore<\/span><span class=\"hljs-selector-class\">.Hosting<\/span> \\\n  <span class=\"hljs-selector-tag\">Microsoft-AspNetCore-Server-Kestrel<\/span> \\\n  <span class=\"hljs-selector-tag\">Microsoft<\/span><span class=\"hljs-selector-class\">.AspNetCore<\/span><span class=\"hljs-selector-class\">.Http<\/span><span class=\"hljs-selector-class\">.Connections<\/span> \\\n  <span class=\"hljs-selector-tag\">System<\/span><span class=\"hljs-selector-class\">.Net<\/span><span class=\"hljs-selector-class\">.Http<\/span> \\\n  <span class=\"hljs-selector-tag\">Microsoft<\/span><span class=\"hljs-selector-class\">.EntityFrameworkCore<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Collect to file:<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">dotnet-counters collect -p <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PID<\/span>&gt;<\/span> -o metrics.json\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">List processes:<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">dotnet-counters ps\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">List counter providers &amp; documentation:<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">dotnet-counters <span class=\"hljs-keyword\">list<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">19. <strong>Putting It All Together (One-Page Summary)<\/strong><\/h1>\n\n\n\n<p><strong>dotnet-counters = Live Performance Insights for .NET Applications<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Category<\/th><th>What You See<\/th><th>Benefit<\/th><\/tr><\/thead><tbody><tr><td>Runtime<\/td><td>CPU, GC, memory, threads, locks<\/td><td>Diagnose bottlenecks<\/td><\/tr><tr><td>ASP.NET Core<\/td><td>RPS, requests, failures<\/td><td>Web performance<\/td><\/tr><tr><td>Kestrel<\/td><td>connections, TLS, queues<\/td><td>Server-level insight<\/td><\/tr><tr><td>System.Net<\/td><td>outbound requests, pools<\/td><td>Networking issues<\/td><\/tr><tr><td>EF Core<\/td><td>queries, contexts, failures<\/td><td>DB performance<\/td><\/tr><tr><td>Diagnostics<\/td><td>warm-up, JIT, timers<\/td><td>Startup tuning<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">20. <strong>Conclusion<\/strong><\/h1>\n\n\n\n<p><strong>dotnet-counters is the single most powerful, lightweight, cross-platform tool for understanding live .NET performance.<\/strong><\/p>\n\n\n\n<p>It gives developers, performance engineers, and SREs the ability to see:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>How much memory is being allocated<\/strong><\/li>\n\n\n\n<li><strong>How often GC is running<\/strong><\/li>\n\n\n\n<li><strong>Whether the app is CPU-bound<\/strong><\/li>\n\n\n\n<li><strong>Whether threads are starving<\/strong><\/li>\n\n\n\n<li><strong>Whether HTTP requests are queuing<\/strong><\/li>\n\n\n\n<li><strong>Whether EF Core is overloaded<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Without restarts.<br>Without downtime.<br>Without profilers.<br>Without risk.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Real-Time Diagnostics for .NET Runtime, ASP.NET Core, EF Core, Networking &amp; More 1. Introduction to dotnet-counters dotnet-counters is a cross-platform performance monitoring tool for .NET applications. It provides real-time metrics&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[11138],"tags":[],"class_list":["post-54155","post","type-post","status-publish","format-standard","hentry","category-best-tools"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54155","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=54155"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54155\/revisions"}],"predecessor-version":[{"id":54157,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54155\/revisions\/54157"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=54155"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=54155"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=54155"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}