Introduction: Why Monitoring is Critical for C# Applications
\n\nIn modern software development, writing code is only half the battle. For an application to run stably, quickly, and predictably, constant monitoring is necessary. For C# (.NET) applications, which are often used in high-load enterprise systems, the banking sector, e-commerce, and cloud services, monitoring becomes not just an option, but a mandatory requirement.
\n\nWithout monitoring, you are working blindly: memory leaks go unnoticed until the server crashes, slow requests accumulate, and users leave for competitors. In this article, we will cover the full cycle of setting up observability for C# applications: from collecting basic metrics to configuring smart alerts in real time.
\n\n1. Monitoring Basics: Which Metrics to Collect in .NET
\n\nBefore setting up tools, it is important to understand which metrics are truly important for C# applications. We will divide them into three groups:
\n\n1.1. System Metrics (Infrastructure Level)
\n- \n
- CPU and Memory — processor load and RAM consumption of the dotnet process. \n
- GC (Garbage Collection) — frequency and duration of garbage collections, heap sizes (Gen0, Gen1, Gen2, LOH). \n
- Thread Pool — number of active, idle, and waiting threads. \n
- Disk I/O and Network — disk read/write, network connections. \n
1.2. Business Metrics (Application Level)
\n- \n
- Request Rate — number of requests per second (RPS). \n
- Latency — response time (p50, p95, p99 percentiles). \n
- Error Rate — percentage of 4xx and 5xx errors. \n
- Active Users — number of concurrently active users. \n
1.3. .NET Runtime Metrics
\n- \n
- JIT Compilation — method compilation time. \n
- Assembly Loading — number of loaded assemblies. \n
- Exceptions — number of thrown exceptions per second. \n
To collect these metrics in .NET, a powerful tool is used — System.Diagnostics.Metrics (built-in API since .NET 6+) and the OpenTelemetry library.
\n\n2. Setting Up Metric Collection with OpenTelemetry and Prometheus
\n\nThe best way to organize monitoring for a C# application is to use the combination of OpenTelemetry (metric collection) + Prometheus (storage) + Grafana (visualization). Let's look at the step-by-step setup.
\n\n2.1. Installing NuGet Packages
\nAdd the following packages to your project:
\ndotnet add package OpenTelemetry.Extensions.Hosting\ndotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore\ndotnet add package OpenTelemetry.Instrumentation.AspNetCore\ndotnet add package OpenTelemetry.Instrumentation.Runtime\n\n2.2. Configuration in Program.cs
\nConfigure OpenTelemetry to automatically collect metrics from ASP.NET Core and .NET Runtime:
\nusing OpenTelemetry.Metrics;\n\nvar builder = WebApplication.CreateBuilder(args);\n\nbuilder.Services.AddOpenTelemetry()\n .WithMetrics(metrics => metrics\n .AddAspNetCoreInstrumentation() // HTTP request metrics\n .AddRuntimeInstrumentation() // GC, JIT, ThreadPool metrics\n .AddPrometheusExporter()); // export to Prometheus\n\nvar app = builder.Build();\n\napp.UseOpenTelemetryPrometheusScrapingEndpoint(); // /metrics endpoint\n\napp.Run();\n\nNow, at http://localhost:5000/metrics, an endpoint with metrics in Prometheus format will be available.
2.3. Creating Custom Metrics
\nLet's add a business metric — a counter for processed orders:
\npublic class OrderMetrics\