Skip to content

Commit e30266a

Browse files
committed
Distributed tracing in networking
1 parent 38c5145 commit e30266a

File tree

14 files changed

+382
-66
lines changed

14 files changed

+382
-66
lines changed
38.1 KB
Loading
39.2 KB
Loading
43.6 KB
Loading
37.3 KB
Loading
95.1 KB
Loading
38.3 KB
Loading
101 KB
Loading
38.1 KB
Loading

docs/fundamentals/networking/telemetry/metrics.md

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ They are also [multi-dimensional](../../../core/diagnostics/metrics-instrumentat
1919
2020
## Collect System.Net metrics
2121

22-
There are two parts to using metrics in a .NET app:
22+
In order to take advangage of the built-in metrics instrumentation, a .NET app needs to be configured to collect these metrics. This typically means transforming them for external storage and analysis, e.g., to monitoring systems.
2323

24-
* **Instrumentation:** Code in .NET libraries takes measurements and associates these measurements with a metric name. .NET and ASP.NET Core include many built-in metrics.
25-
* **Collection:** A .NET app configures named metrics to be transmitted from the app for external storage and analysis. Some tools might perform configuration outside the app using configuration files or a UI tool.
24+
There are several ways of collecting networking metrics in .NET.
25+
- For a quick overview using a simple, self-contained example, see [collecting metrics with dotnet-counters](#collecting-metrics-with-dotnet-counters).
26+
- For **production-time** metrics collection and monitoring, you can use [Grafana with OpenTelemetry and Prometheus](#view-metrics-in-grafana-with-opentelemetry-and-prometheus) or [Azure Monitor Application Insights](../../../core/diagnostics/observability-applicationinsights.md). However, these tools are quite complex, and may be inconvenient to use at development time.
27+
- For **development-time** metrics collection and troubleshooting we recommend to use [.NET Aspire](#collecting-metrics-with-net-aspire), which provides a simple, but extensible way to kickstart metrics and distributed tracing in your application and to diagnose issues locally.
28+
- It is also possible to [reuse the Aspire Service Defaults](#reusing-service-defaults-project-without-net-aspire-orchestration) project without the Aspire orchestration. This is a handy way to introduce the OpenTelemetry tracing and metrics configuration API-s into your ASP.NET project.
2629

27-
This section demonstrates various methods to collect and view System.Net metrics.
30+
### Collecting metrics with dotnet-counters
2831

29-
### Example app
32+
[`dotnet-counters`](../../../core/diagnostics/dotnet-counters.md) is a cross-platform performance monitoring tool for ad-hoc health monitoring and first-level performance investigation.
3033

3134
For the sake of this tutorial, create a simple app that sends HTTP requests to various endpoints in parallel.
3235

@@ -39,9 +42,7 @@ Replace the contents of `Program.cs` with the following sample code:
3942

4043
:::code language="csharp" source="snippets/metrics/Program.cs" id="snippet_ExampleApp":::
4144

42-
### View metrics with dotnet-counters
43-
44-
[`dotnet-counters`](../../../core/diagnostics/dotnet-counters.md) is a cross-platform performance monitoring tool for ad-hoc health monitoring and first-level performance investigation.
45+
Make sure `dotnet-counters` is installed:
4546

4647
```dotnetcli
4748
dotnet tool install --global dotnet-counters
@@ -52,96 +53,102 @@ When running against a .NET 8+ process, `dotnet-counters` enables the instrument
5253
```console
5354
dotnet-counters monitor --counters System.Net.Http,System.Net.NameResolution -n HelloBuiltinMetrics
5455
```
56+
### Collecting metrics with .NET Aspire
5557

56-
### View metrics in Grafana with OpenTelemetry and Prometheus
58+
The simplest solution for collecting metrics for ASP.NET applications is to use [.NET Aspire](/dotnet/aspire/get-started/aspire-overview) which is a set of extensions to .NET to make it easy to create and work with distributed applications. One of the benefits of using .NET Aspire is that telemetry is built in, using the OpenTelemetry libraries for .NET.
5759

58-
#### Overview
60+
The default project templates for .NET Aspire contain a `ServiceDefaults` project, part of which is to setup and configure OTel. The Service Defaults project is referenced and initialized by each service in a .NET Aspire solution.
5961

60-
[OpenTelemetry](https://opentelemetry.io/):
62+
The Service Defaults project template includes the OTel SDK, ASP.NET, HttpClient and Runtime Instrumentation packages, and those are configured in the [`Extensions.cs`](https://github.com/dotnet/aspire/blob/main/src/Aspire.ProjectTemplates/templates/aspire-servicedefaults/Extensions.cs) file. For exporting telemetry .NET Aspire includes the OTLP exporter by default so that it can provide telemetry visualization using the Aspire Dashboard.
6163

62-
- Is a vendor-neutral, open-source project supported by the [Cloud Native Computing Foundation](https://www.cncf.io/).
63-
- Standardizes generating and collecting telemetry for cloud-native software.
64-
- Works with .NET using the .NET metric APIs.
65-
- Is endorsed by [Azure Monitor](/azure/azure-monitor/app/opentelemetry-overview) and many APM vendors.
64+
The Aspire Dashboard is designed to bring telemetry observation to the local debug cycle, which enables developers to not only ensure that the applications are producing telemetry, but also use that telemetry to diagnose those applications locally. Being able to observe the calls between services is proving to be just as useful at debug time as in production. The .NET Aspire dashboard is launched automatically when you F5 the `AppHost` Project from Visual Studio or `dotnet run` the `AppHost` project.
6665

67-
This tutorial shows one of the integrations available for OpenTelemetry metrics using the OSS [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) projects. The metrics data flow consists of the following steps:
66+
#### Quick walkthrough
6867

69-
1. The .NET metric APIs record measurements from the example app.
70-
1. The OpenTelemetry library running in the app aggregates the measurements.
71-
1. The Prometheus exporter library makes the aggregated data available via an HTTP metrics endpoint. 'Exporter' is what OpenTelemetry calls the libraries that transmit telemetry to vendor-specific backends.
72-
1. A Prometheus server:
68+
1. Create a **.NET Aspire 9 Starter App** by using `dotnet new`:
7369

74-
- Polls the metrics endpoint.
75-
- Reads the data.
76-
- Stores the data in a database for long-term persistence. Prometheus refers to reading and storing data as *scraping* an endpoint.
77-
- Can run on a different machine.
70+
```dotnetcli
71+
dotnet new aspire-starter-9 --output AspireDemo
72+
```
7873

79-
1. The Grafana server:
74+
Or in Visual Studio:
8075

81-
- Queries the data stored in Prometheus and displays it on a web-based monitoring dashboard.
82-
- Can run on a different machine.
76+
![Create a .NET Aspire 9 Starter App in Visual Studio](media/aspire-starter.png)
8377

84-
#### Configure the example app to use OpenTelemetry's Prometheus exporter
78+
2. Open `Extensions.cs` in the `ServiceDefaults` project, and scroll to the `ConfigureOpenTelemetry` method. Notice the `AddHttpClientInstrumentation()` call subscribing to the networking meters.
8579

86-
Add a reference to the OpenTelemetry Prometheus exporter to the example app:
80+
:::code language="csharp" source="snippets/tracing/ConnectionTracingDemo.ServiceDefaults/Extensions.cs" id="snippet_Metrics" highlight="3":::
8781

88-
```dotnetcli
89-
dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener --prerelease
82+
Note that on .NET 8+, `AddHttpClientInstrumentation()` can be replaced by manual meter subscription:
83+
84+
```csharp
85+
.WithMetrics(metrics =>
86+
{
87+
metrics.AddAspNetCoreInstrumentation()
88+
.AddMeter("System.Net.Http")
89+
.AddMeter("System.Net.NameResolution")
90+
.AddRuntimeInstrumentation();
91+
})
9092
```
9193

92-
> [!NOTE]
93-
> This tutorial uses a pre-release build of OpenTelemetry's Prometheus support available at the time of writing.
94+
3. Run the `AppHost` project. This should launch the Aspire Dashboard.
9495

95-
Update `Program.cs` with OpenTelemetry configuration:
96+
4. Navigate to the Weather page of the `webfrontend` app to generate an `HttpClient` request towards `apiservice`. Refresh the page several times to send multiple requests.
9697

97-
:::code language="csharp" source="snippets/metrics/Program.cs" id="snippet_PrometheusExporter" highlight="5-8":::
98+
5. Return to the Dashboard, navigate to the **Metrics** page and select the `webfrontend` resource. Srolling down, you should be able to browse the built-in `System.Net` metrics.
9899

99-
In the preceding code:
100+
[![Networking metrics in Aspire Dashboard](media/aspire-metrics-thumb.png)](media/aspire-metrics.png#lightbox)
100101

101-
- `AddMeter("System.Net.Http", "System.Net.NameResolution")` configures OpenTelemetry to transmit all the metrics collected by the built-in `System.Net.Http` and `System.Net.NameResolution` meters.
102-
- `AddPrometheusHttpListener` configures OpenTelemetry to expose Prometheus' metrics HTTP endpoint on port `9184`.
102+
For more details on .NET Aspire see:
103103

104-
> [!NOTE]
105-
> This configuration differs for ASP.NET Core apps, where metrics are exported with `OpenTelemetry.Exporter.Prometheus.AspNetCore` instead of `HttpListener`. See the [related ASP.NET Core example](/aspnet/core/log-mon/metrics/metrics#create-the-starter-app).
104+
- [Aspire Overview](/dotnet/aspire/get-started/aspire-overview)
105+
- [Telemetry in Aspire](/dotnet/aspire/fundamentals/telemetry)
106+
- [Aspire Dashboard](/dotnet/aspire/fundamentals/dashboard/explore)
106107

107-
Run the app and leave it running so measurements can be collected:
108+
### Reusing Service Defaults project without .NET Aspire Orchestration
108109

109-
```dotnetcli
110-
dotnet run
111-
```
110+
Probably the easiest way to configure OTel for ASP.NET projects is to use the Aspire Service Defaults project, even if not using the rest of .NET Aspire such as the AppHost for orchestration. The Service Defaults project is available as a project template via Visual Studio or `dotnet new`. It configures OTel and sets up the OTLP exporter. You can then use the [OTel environment variables](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Exporter.OpenTelemetryProtocol#exporter-configuration) to configure the OTLP endpoint to send telemetry to, and provide the resource properties for the application.
112111

113-
#### Set up and configure Prometheus
112+
The steps to use *ServiceDefaults* outside .NET Aspire are:
114113

115-
Follow the [Prometheus first steps](https://prometheus.io/docs/introduction/first_steps/) to set up a Prometheus server and confirm it is working.
114+
- Add the *ServiceDefaults* project to the solution using Add New Project in Visual Studio, or use `dotnet new aspire-servicedefaults --output ServiceDefaults`
115+
- Reference the *ServiceDefaults* project from your ASP.NET application. In Visual Studio use "Add -> Project Reference" and select the *ServiceDefaults* project"
116+
- Call its OpenTelemetry setup function as part of your application builder initialization.
116117

117-
Modify the *prometheus.yml* configuration file so that Prometheus scrapes the metrics endpoint that the example app is exposing. Add the following highlighted text in the `scrape_configs` section:
118+
``` csharp
119+
var builder = WebApplication.CreateBuilder(args);
120+
builder.ConfigureOpenTelemetry();
118121

119-
:::code language="yaml" source="snippets/metrics/prometheus.yml" highlight="31-99":::
122+
var app = builder.Build();
120123

121-
#### Start prometheus
124+
app.MapGet("/", () => "Hello World!");
122125

123-
1. Reload the configuration or restart the Prometheus server.
124-
1. Confirm that OpenTelemetryTest is in the UP state in the **Status** > **Targets** page of the Prometheus web portal.
125-
![Prometheus status](~/docs/core/diagnostics/media/prometheus-status.png)
126+
app.Run();
127+
```
126128

127-
1. On the Graph page of the Prometheus web portal, enter `http` in the expression text box and select `http_client_active_requests`.
128-
![http_client_active_requests](~/docs/fundamentals/networking/telemetry/media/prometheus-search.png)
129-
In the graph tab, Prometheus shows the value of the `http.client.active_requests` counter that's emitted by the example app.
130-
![Prometheus active requests graph](~/docs/fundamentals/networking/telemetry/media/prometheus-active-requests.png)
129+
For a full walkthrough, see [Example: Use OpenTelemetry with OTLP and the standalone Aspire Dashboard](../../../core/diagnostics/observability-otlp-example.md).
131130

132-
#### Show metrics on a Grafana dashboard
131+
### View metrics in Grafana with OpenTelemetry and Prometheus
133132

134-
1. Follow the [standard instructions](https://prometheus.io/docs/visualization/grafana/#installing) to install Grafana and connect it to a Prometheus data source.
133+
Please follow our tutorial on [Using OpenTelemetry with Prometheus, Grafana, and Jaeger](../../../core/diagnostics/observability-prgrja-example.md).
135134

136-
1. Create a Grafana dashboard by selecting the **+** icon on the top toolbar then selecting **Dashboard**. In the dashboard editor that appears, enter **Open HTTP/1.1 Connections** in the **Title** box and the following query in the PromQL expression field:
135+
Note that the tutorial does not particularly discuss `HttpClient` metrics. In order to enable them, it is necessary to extend the [metrics configuration code](../../../core/diagnostics/observability-prgrja-example.md#5-configure-opentelemetry-with-the-correct-providers) with the addition of the `System.Net.*` meters:
137136

137+
```csharp
138+
otel.WithMetrics(metrics => metrics
139+
// Metrics provider from OpenTelemetry
140+
.AddAspNetCoreInstrumentation()
141+
.AddMeter(greeterMeter.Name)
142+
// Metrics provided by ASP.NET Core in .NET 8
143+
.AddMeter("Microsoft.AspNetCore.Hosting")
144+
.AddMeter("Microsoft.AspNetCore.Server.Kestrel")
145+
// Metrics provided by System.Net libraries
146+
.AddMeter("System.Net.Http")
147+
.AddMeter("System.Net.NameResolution")
148+
.AddPrometheusExporter());
138149
```
139-
sum by(http_connection_state) (http_client_open_connections{network_protocol_version="1.1"})
140-
```
141-
142-
![Grafana HTTP/1.1 Connections](~/docs/fundamentals/networking/telemetry/media/grafana-connections.png)
143150

144-
1. Select **Apply** to save and view the new dashboard. It displays the number of active vs idle HTTP/1.1 connections in the pool.
151+
Moreover, `HttpClient(Factory)` usage is needed to see the `System.Net` metrics in action. The `/NestedGreeting` endpoint in the paragraph [Distributed tracing with Jaeger](../../../core/diagnostics/observability-prgrja-example.md#9-distributed-tracing-with-jaeger) provides a simple example for that.
145152

146153
## Enrichment
147154

docs/fundamentals/networking/telemetry/overview.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ ms.date: 10/18/2022
88

99
# Networking telemetry in .NET
1010

11-
The .NET networking stack is instrumented at various layers. .NET gives you the option to collect accurate timings throughout the lifetime of an HTTP request using metrics, event counters, and events.
11+
The .NET networking stack is instrumented at various layers. .NET gives you the option to collect accurate timings throughout the lifetime of an HTTP request using metrics, distributed tracing, event counters, and events.
1212

13-
- **[Networking metrics](metrics.md)**: Starting with .NET 8, the HTTP and the name resolution (DNS) components are instrumented using the modern [System.Diagnostics.Metrics API](../../../core/diagnostics/metrics.md). These metrics were designed in cooperation with [OpenTelemetry](https://opentelemetry.io/).
13+
- **[Networking metrics](metrics.md)**: Starting with .NET 8, the HTTP and the name resolution (DNS) components are instrumented using the modern [System.Diagnostics.Metrics API](../../../core/diagnostics/metrics.md). These metrics were designed in cooperation with [OpenTelemetry](https://opentelemetry.io/) and can be exported to various monitoring tools.
14+
- **[Distributed tracing](tracing.md)**: `HttpClient` is instrumented to emit [distributed tracing](../../../core/diagnostics/distributed-tracing.md) activities (a.k.a., spans).
1415
- **[Networking events](events.md)**: Events provide debug and trace information with accurate timestamps.
1516
- **[Networking event counters](event-counters.md)**: All networking components are instrumented to publish real-time performance metrics using the EventCounters API.
1617

0 commit comments

Comments
 (0)