Skip to content

Commit

Permalink
Misc diagnostic doc cleanup (#42359)
Browse files Browse the repository at this point in the history
* Misc diagnostic doc cleanup

I was recently reviewing the diagnostic docs and accumulated a variety of small fixes, improvements, and updates:

- Added links to using the Meters to the built-in metrics pages that didn't have one.
- Moved links for EventCounters and PerformanceCounters to the bottom of built-in-metrics.md to make it clearer these are different from the System.Diagnostics.Metrics API and to avoid being a distraction.
- On the comparison pages for both metrics and logging I significantly reduced content about terminology and principles that is fairly generalized across all languages that have these features. I am assuming that most readers are either familiar with the basics already or they can learn it elsewhere. This reduces abstraction, allows the reader to get to the .NET specific APIs much quicker, and ensures that the top-most recommended API should be visible without needing to scroll down.
- Updated references to out-of-date OpenTelemetry packages and removed usage of the obsolete StartWithHost() OTel API.
- Updated some example snippets to remove nullability build warnings
- Fixed a compilation error where a metrics snippet refered to a non-existant overload of Random.GetNext()
- Updated the output of several examples to account for changes in OTel console exporter and dotnet-counters output
- Updated some of the old examples to use newer SDK versions
- Adjusted warnings about dotnet-trace bitness matching that appear to no longer be accurate. In the past there apparently was an issue calling Process.GetProcessById() and potentially other System.Diagnostic.Process functions when the application bitness running the code didn't match the bitness of the process being inspected. Testing now I didn't detect any issues running x86 dotnet-trace against a 64 bit target process or vice versa with one exception - x86 dotnet-trace doesn't correctly show the command lines of 64 bit apps in the ps command.
- Removed some spurious warnings about using dotnet-trace with apps older than .NET 5. The doc already mentions .NET 5+ is supported so there seemed no need to keep repeating it.
- Removed the dotnet-trace EventCounter collection example. The functionality should still work but this seems like an obscure scenario that would rarely be useful. I didn't want to give the impression this was a common technique we expect users to need or encourage them to do. Using dotnet-counters or dotnet-monitor would be a more natural and convenient approach to collect that data ad-hoc.
- Added a note to EventCounters about the newer Metrics API to ensure readers are aware this older API is not the preferred one in most scenarios.
- Added information about the Gauge instrument that was added during .NET 8.
- Removed/adjusted some discussion about the dotnet-counters output format that is no longer accurate given recent changes to the tool's output behavior.
- Adjusted the stack overflow debugging example to account for the stacktrace that is shown in all currently supported versions of the runtime.

* Apply suggestions from code review

Co-authored-by: Genevieve Warren <[email protected]>

* Applying review feedback

---------

Co-authored-by: Genevieve Warren <[email protected]>
  • Loading branch information
noahfalk and gewarren authored Sep 4, 2024
1 parent 76d8ac2 commit e5b0850
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 197 deletions.
3 changes: 3 additions & 0 deletions docs/core/diagnostics/built-in-metrics-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ ms.date: 11/02/2023
This article describes the built-in metrics for diagnostic .NET extensions libraries that are produced using the
<xref:System.Diagnostics.Metrics?displayProperty=nameWithType> API. For a listing of metrics based on the older [EventCounters](event-counters.md) API, see [Available counters](available-counters.md).

> [!TIP]
> For more information about how to collect and report these metrics, see [Collecting Metrics](metrics-collection.md).
## `Microsoft.Extensions.Diagnostics.HealthChecks`

The `Microsoft.Extensions.Diagnostics.HealthChecks` metrics report health check information from [.NET health checks](diagnostic-health-checks.md):
Expand Down
3 changes: 3 additions & 0 deletions docs/core/diagnostics/built-in-metrics-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ ms.date: 11/02/2023
This article describes the built-in metrics for .NET runtime libraries that are produced using the
<xref:System.Diagnostics.Metrics?displayProperty=nameWithType> API. For a listing of metrics based on the older [EventCounters](event-counters.md) API, see [Available counters](available-counters.md).

> [!TIP]
> For more information about how to collect and report these metrics, see [Collecting Metrics](metrics-collection.md).
## `System.Runtime`

The `System.Runtime` Meter reports measurements from the GC, JIT, AssemblyLoader, Threadpool, and exception handling portions of the .NET runtime as well as some CPU and memory metrics from the OS. These metrics are available automatically for all .NET apps.
Expand Down
8 changes: 6 additions & 2 deletions docs/core/diagnostics/built-in-metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ ms.date: 11/02/2023
# Built-in metrics in .NET

This is a reference for [metrics](metrics.md) built-in for .NET, produced using the
<xref:System.Diagnostics.Metrics?displayProperty=nameWithType> API. For metrics produced by [alternative metric APIs](compare-metric-apis.md)
see the [EventCounters reference](available-counters.md) and [Windows Performance Counter reference](../../framework/debug-trace-profile/performance-counters.md).
<xref:System.Diagnostics.Metrics?displayProperty=nameWithType> API.

- [.NET runtime metrics](built-in-metrics-runtime.md)
- [.NET extensions metrics](built-in-metrics-diagnostics.md)
- [ASP.NET Core Metrics](built-in-metrics-aspnetcore.md)
- [System.Net Metrics](built-in-metrics-system-net.md)
- [Entity Framework Core Metrics](/ef/core/logging-events-diagnostics/metrics)

## Older metric APIs

For built-in metrics produced by [alternative metric APIs](compare-metric-apis.md)
see the [EventCounters reference](available-counters.md) and [Windows Performance Counter reference](../../framework/debug-trace-profile/performance-counters.md).
27 changes: 5 additions & 22 deletions docs/core/diagnostics/compare-metric-apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,10 @@ ms.date: 11/04/2021
# Metric APIs comparison

When adding new metric instrumentation to a .NET app or library, there are various different APIs to choose from. This article
will help you understand what is available and some of the tradeoffs involved.

There are two major categories of APIs, vendor-neutral and vendor-specific.
Vendor-specific APIs have the advantage that the vendor can iterate their designs quickly, add specialized features, and achieve
tight integration between their instrumentation APIs and their backend systems. As an example, if you instrumented your app with
metric APIs provided by [Application Insights](/azure/azure-monitor/app/app-insights-overview), then
you would expect to find well-integrated functionality and all of Application Insight's latest features when working with their
analysis tools. However the library or app would also now be coupled to this vendor and changing to a different one in the future
would require rewriting the instrumentation. For libraries, this coupling can be particularly problematic because the library
developer might use one vendor's API and the app developer that references the library wants to work with a different vendor.
To resolve this coupling issue, vendor-neutral options provide a standardized API façade and extensibility
points to route data to various vendor backend systems depending on configuration. However, vendor-neutral APIs may provide
fewer capabilities, and you're still constrained to pick a vendor that has integrated with the façade's extensibility
mechanism.
will help you understand the options.

## .NET APIs

Over .NET's 20+ year history, we've iterated a few times on the design for metric APIs, all of which are supported and vendor-neutral:

### System.Diagnostics.Metrics

[System.Diagnostics.Metrics](metrics-instrumentation.md) APIs are the newest cross-platform APIs, and were designed in close collaboration with the
Expand All @@ -44,7 +29,7 @@ Although this API was designed to work well with OpenTelemetry and its growing e

### PerformanceCounter

<xref:System.Diagnostics.PerformanceCounter?displayProperty=nameWithType> APIs are the oldest metric APIs. They're only supported on Windows and provide
<xref:System.Diagnostics.PerformanceCounter?displayProperty=nameWithType> APIs are the oldest .NET metric APIs. They're only supported on Windows and provide
a managed wrapper for Windows OS [Performance Counter](/windows/win32/perfctrs/performance-counters-portal)
technology. They are available in all supported versions of .NET.

Expand All @@ -56,9 +41,8 @@ For more information, see [Performance counters in .NET Framework](../../framewo

### EventCounters

The [EventCounters](event-counters.md) API came next after `PerformanceCounters`. This API aimed to provide a uniform
cross-platform experience. The APIs are available by targeting .NET Core 3.1+, and a small subset is available on .NET Framework 4.7.1
and later. These APIs are fully supported and are actively used by key .NET libraries, but they
The [EventCounters](event-counters.md) were the first .NET APIs to support a cross-platform metrics experience. The APIs are available by targeting .NET Core 3.1+, and a small subset is available on .NET Framework 4.7.1
and later. These APIs are fully supported and still used by key .NET libraries, but they
have less functionality than the newer <xref:System.Diagnostics.Metrics?displayProperty=nameWithType> APIs. EventCounters are able to report
rates of change and averages, but do not support histograms and percentiles. There is also no support for multi-dimensional metrics. Custom
tooling is possible via the <xref:System.Diagnostics.Tracing.EventListener> API, though it is not strongly typed, only gives
Expand All @@ -67,8 +51,7 @@ access to the aggregated values, and has limitations when using more than one li
[dotnet-counters](dotnet-counters.md), and [dotnet-monitor](https://devblogs.microsoft.com/dotnet/introducing-dotnet-monitor/). For third-party
tool support, check the vendor or project documentation to see if it's available.

The .NET team doesn't expect to make substantial new investments on this API going forward, but as with `PerformanceCounters`, the API remains
actively supported for all current and future users.
The .NET team doesn't expect to make new investments on this API going forward, but as with `PerformanceCounters`, the API remains supported for all current and future users.

## Third-party APIs

Expand Down
16 changes: 11 additions & 5 deletions docs/core/diagnostics/debug-stackoverflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Debugging StackOverflow errors
description: Learn how to diagnose StackOverflow exceptions
ms.topic: tutorial
ms.date: 12/22/2020
ms.date: 8/22/2024
---
# Debug StackOverflow errors

Expand Down Expand Up @@ -30,13 +30,19 @@ The `Main` method will continuously call itself until there is no more stack spa
````
> dotnet run
Stack overflow.
at temp.Program.Main(System.String[])
at temp.Program.Main(System.String[])
at temp.Program.Main(System.String[])
at temp.Program.Main(System.String[])
at temp.Program.Main(System.String[])
at temp.Program.Main(System.String[])
<this output repeats many more times>
````

> [!NOTE]
> On .NET 5 and later, the callstack is output to the console.
Often just seeing this callstack is enough to identify the problematic repeating method and locate the source code logic that is causing the recursive calls. However if the problem is still unclear you can debug further.

> [!NOTE]
> This article describes how to debug a stack overflow with lldb. If you are running on Windows, we suggest debugging the app with [Visual Studio](/visualstudio/debugger/what-is-debugging) or [Visual Studio Code](https://code.visualstudio.com/Docs/editor/debugging).
> This article describes how to debug a stack overflow with lldb on Linux. If you are running on Windows, we suggest debugging the app with [Visual Studio](/visualstudio/debugger/what-is-debugging) or [Visual Studio Code](https://code.visualstudio.com/Docs/editor/debugging).
## Example

Expand Down Expand Up @@ -97,7 +103,7 @@ Stack overflow.
Source file: /temp/Program.cs @ 9
````

5. Go look at the indicated method temp.Program.Main(System.String[]) and source "/temp/Program.cs @ 9" to see if you can figure out what you did wrong. If it still wasn't clear you could add logging in that area of the code.
5. Go look at the indicated method temp.Program.Main(System.String[]) and source "/temp/Program.cs @ 9" to see if you can figure out what you did wrong. If it still wasn't clear you could use further debugger commands to inspect the current state of the process or add logging in that area of the code.

## See Also

Expand Down
134 changes: 71 additions & 63 deletions docs/core/diagnostics/distributed-tracing-collection-walkthroughs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Collect a distributed trace - .NET
description: Tutorials to collect distributed traces in .NET applications using OpenTelemetry, Application Insights, or ActivityListener
ms.topic: tutorial
ms.date: 03/14/2021
ms.date: 08/27/2024
---

# Collect a distributed trace
Expand All @@ -27,7 +27,7 @@ configure OpenTelemetry to send information elsewhere, see the

#### Prerequisites

- [.NET Core 7.0 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version
- [.NET Core 8.0 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version

#### Create an example application

Expand All @@ -45,16 +45,12 @@ if we browse the web page.
To use OpenTelemetry, you need to add references to several NuGet packages.

```dotnetcli
dotnet add package OpenTelemetry --version 1.4.0-rc1
dotnet add package OpenTelemetry.Exporter.Console --version 1.4.0-rc1
dotnet add package OpenTelemetry.Extensions.Hosting --version 1.4.0-rc1
dotnet add package OpenTelemetry.Instrumentation.AspNetCore --version 1.0.0-rc9.10
dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.Console
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
```

> [!NOTE]
> At the time of writing, the 1.4.0 Release Candidate 1 build was the latest version of OpenTelemetry available. Once a final version
> is available, use that instead.
Next, modify the source code in *Program.cs* so it looks like this:

```csharp
Expand All @@ -70,7 +66,7 @@ builder.Services.AddOpenTelemetry()
{
builder.AddAspNetCoreInstrumentation();
builder.AddConsoleExporter();
}).StartWithHost();
});

var app = builder.Build();

Expand Down Expand Up @@ -98,26 +94,28 @@ Run the app and use a web browser to browse to the web page being hosted. Now th
tracing, you should see information about the browser web requests printed to the console:

```
Activity.TraceId: 9c4519ce65a667280daedb3808d376f0
Activity.SpanId: 727c6a8a6cff664f
Activity.TraceId: 4510acfc49c6f8a582c6a40004df9a76
Activity.SpanId: 65fe2c5c15f05ed8
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName: /
Activity.DisplayName: GET
Activity.Kind: Server
Activity.StartTime: 2023-01-08T01:56:05.4529879Z
Activity.Duration: 00:00:00.1048255
Activity.StartTime: 2024-08-27T23:12:58.7837908Z
Activity.Duration: 00:00:00.1297070
Activity.Tags:
net.host.name: localhost
net.host.port: 5163
http.method: GET
http.scheme: http
http.target: /
http.url: http://localhost:5163/
http.flavor: 1.1
http.user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76
http.status_code: 200
server.address: localhost
server.port: 5005
http.request.method: GET
url.scheme: http
url.path: /
network.protocol.version: 1.1
user_agent.original: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0
http.response.status_code: 200
Resource associated with Activity:
service.name: unknown_service:demo
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
service.name: unknown_service:webapp
```

All of the OpenTelemetry configuration occurs in the new source lines that start with `builder.Services.AddOpenTelemetry()`. You used
Expand All @@ -131,7 +129,7 @@ another monitoring service you've chosen to use.

#### Prerequisites

- [.NET Core 2.1 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version
- [.NET Core 8.0 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version

#### Create an example application

Expand All @@ -149,10 +147,6 @@ Applications that target .NET 5 and later already have the necessary distributed
.NET versions, add the [System.Diagnostics.DiagnosticSource NuGet package](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/)
version 5 or greater.

```dotnetcli
dotnet add package System.Diagnostics.DiagnosticSource
```

Replace the contents of the generated Program.cs with this example source:

```csharp
Expand All @@ -174,7 +168,7 @@ namespace Sample.DistributedTracing

static async Task DoSomeWork()
{
using (Activity a = s_source.StartActivity("SomeWork"))
using (Activity? a = s_source.StartActivity("SomeWork"))
{
await StepOne();
await StepTwo();
Expand All @@ -183,15 +177,15 @@ namespace Sample.DistributedTracing

static async Task StepOne()
{
using (Activity a = s_source.StartActivity("StepOne"))
using (Activity? a = s_source.StartActivity("StepOne"))
{
await Task.Delay(500);
}
}

static async Task StepTwo()
{
using (Activity a = s_source.StartActivity("StepTwo"))
using (Activity? a = s_source.StartActivity("StepTwo"))
{
await Task.Delay(1000);
}
Expand Down Expand Up @@ -246,34 +240,52 @@ Now the app collects distributed trace information and displays it to the consol

```dotnetcli
> dotnet run
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-6081a9b8041cd840-01
Activity.ParentId: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: StepOne
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:46.8649754Z
Activity.Duration: 00:00:00.5069226
Activity.TraceId: 48d7509cc4f06db6f48f2207f19c3918
Activity.SpanId: 406a1de6b5e8192e
Activity.TraceFlags: Recorded
Activity.ParentSpanId: 345f5f98015b589a
Activity.ActivitySourceName: Sample.DistributedTracing
Activity.DisplayName: StepOne
Activity.Kind: Internal
Activity.StartTime: 2024-08-27T23:22:44.9900801Z
Activity.Duration: 00:00:00.5077426
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-d2b283db91cf774c-01
Activity.ParentId: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: StepTwo
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:47.3838737Z
Activity.Duration: 00:00:01.0142278
service.instance.id: a87f9e7d-d28c-4a91-9bb3-939a50cac7db
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
Activity.TraceId: 48d7509cc4f06db6f48f2207f19c3918
Activity.SpanId: 458fb58342ca127a
Activity.TraceFlags: Recorded
Activity.ParentSpanId: 345f5f98015b589a
Activity.ActivitySourceName: Sample.DistributedTracing
Activity.DisplayName: StepTwo
Activity.Kind: Internal
Activity.StartTime: 2024-08-27T23:22:45.5906581Z
Activity.Duration: 00:00:01.0023729
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
service.instance.id: a87f9e7d-d28c-4a91-9bb3-939a50cac7db
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:46.8634510Z
Activity.Duration: 00:00:01.5402045
Activity.TraceId: 48d7509cc4f06db6f48f2207f19c3918
Activity.SpanId: 345f5f98015b589a
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Sample.DistributedTracing
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2024-08-27T23:22:44.9894135Z
Activity.Duration: 00:00:01.6059128
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
service.instance.id: a87f9e7d-d28c-4a91-9bb3-939a50cac7db
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
Example work done
```
Expand Down Expand Up @@ -316,7 +328,7 @@ it to the console.

### Prerequisites

- [.NET Core 2.1 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version
- [.NET Core 8.0 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version

### Create an example application

Expand All @@ -330,10 +342,6 @@ Applications that target .NET 5 and later already have the necessary distributed
.NET versions, add the [System.Diagnostics.DiagnosticSource NuGet package](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/)
version 5 or greater.

```dotnetcli
dotnet add package System.Diagnostics.DiagnosticSource
```

Replace the contents of the generated Program.cs with this example source:

```csharp
Expand All @@ -355,7 +363,7 @@ namespace Sample.DistributedTracing

static async Task DoSomeWork()
{
using (Activity a = s_source.StartActivity("SomeWork"))
using (Activity? a = s_source.StartActivity("SomeWork"))
{
await StepOne();
await StepTwo();
Expand All @@ -364,15 +372,15 @@ namespace Sample.DistributedTracing

static async Task StepOne()
{
using (Activity a = s_source.StartActivity("StepOne"))
using (Activity? a = s_source.StartActivity("StepOne"))
{
await Task.Delay(500);
}
}

static async Task StepTwo()
{
using (Activity a = s_source.StartActivity("StepTwo"))
using (Activity? a = s_source.StartActivity("StepTwo"))
{
await Task.Delay(1000);
}
Expand Down
Loading

0 comments on commit e5b0850

Please sign in to comment.