Add IMeterFactory best practice to ASP.NET Core metrics (#30073)

Co-authored-by: Rick Anderson <3605364+Rick-Anderson@users.noreply.github.com>
pull/30179/head
James Newton-King 2023-08-29 11:55:19 +08:00 committed by GitHub
parent 02411fe718
commit e1edded975
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 47 additions and 2 deletions

View File

@ -91,7 +91,52 @@ For more information, see [dotnet-counters](/dotnet/core/diagnostics/dotnet-coun
## Create custom metrics ## Create custom metrics
See [Create custom metrics](/dotnet/core/diagnostics/metrics#create-custom-metrics) for information on creating custom metrics. Metrics are created using APIs in the <xref:System.Diagnostics.Metrics> namespace. See [Create custom metrics](/dotnet/core/diagnostics/metrics-instrumentation#create-a-custom-metric) for information on creating custom metrics.
### Creating metrics in ASP.NET Core apps with `IMeterFactory`
We recommended creating `Meter` instances in ASP.NET Core apps with <xref:System.Diagnostics.Metrics.IMeterFactory>.
ASP.NET Core registers <xref:System.Diagnostics.Metrics.IMeterFactory> in dependency injection (DI) by default. The meter factory integrates metrics with DI, making isolating and collecting metrics easy. `IMeterFactory` is especially useful for testing. It allows for multiple tests to run side-by-side and only collecting metrics values that are recorded in a test.
To use `IMeterFactory` in an app, create a type that uses `IMeterFactory` to create the app's custom metrics:
```cs
public class ContosoMetrics
{
private readonly Counter<int> _productSoldCounter;
public ContosoMetrics(IMeterFactory meterFactory)
{
var meter = meterFactory.CreateMeter("Contoso.Web");
_productSoldCounter = meter.CreateCounter<int>("contoso.product.sold");
}
public void ProductSold(string productName, int quantity)
{
_productSoldCounter.Add(quantity,
new KeyValuePair<string, object?>("contoso.product.name", productName));
}
}
```
Register the metrics type with DI in `Program.cs`:
```cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ContosoMetrics>();
```
Inject the metrics type and record values where needed. Because the metrics type is registered in DI it can be use with MVC controllers, minimal APIs, or any other type that is created by DI:
```cs
app.MapPost("/complete-sale", ([FromBody] SaleModel model, ContosoMetrics metrics) =>
{
// ... business logic such as saving the sale to a database ...
metrics.ProductSold(model.QuantitySold, model.ProductName);
});
```
## View metrics in Grafana with OpenTelemetry and Prometheus ## View metrics in Grafana with OpenTelemetry and Prometheus
@ -208,7 +253,7 @@ The proceeding test:
* Bootstraps a web app in memory with <xref:Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory%601>. `Program` in the factory's generic argument specifies the web app. * Bootstraps a web app in memory with <xref:Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory%601>. `Program` in the factory's generic argument specifies the web app.
* Collects metrics values with <xref:Microsoft.Extensions.Telemetry.Testing.Metering.MetricCollector%601>. * Collects metrics values with <xref:Microsoft.Extensions.Telemetry.Testing.Metering.MetricCollector%601>.
* Requires a package reference to `Microsoft.Extensions.Telemetry.Testing`. * Requires a package reference to `Microsoft.Extensions.Telemetry.Testing`.
* The `MetricCollector` is created using the web app's `IMeterFactory`. This allows the collector to only report metrics values recorded by test. * The `MetricCollector<T>` is created using the web app's <xref:System.Diagnostics.Metrics.IMeterFactory>. This allows the collector to only report metrics values recorded by test.
* Includes the meter name, `Microsoft.AspNetCore.Hosting`, and counter name, `http.server.request.duration` to collect. * Includes the meter name, `Microsoft.AspNetCore.Hosting`, and counter name, `http.server.request.duration` to collect.
* Makes an HTTP request to the web app. * Makes an HTTP request to the web app.
* Asserts the test using results from the metrics collector. * Asserts the test using results from the metrics collector.