-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Update distributed tracing docs #23313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
2ffd9de
Update distributed tracing docs
noahfalk a83e344
Applying review feedback
noahfalk 1170982
Adding OTel resource
noahfalk bba5da2
Updating toc
noahfalk 269e248
Fix xref
noahfalk 14101c7
Addressing more feedback
noahfalk 44d5d5e
More feedback
noahfalk 982f4b1
newline
noahfalk 4d79420
last touchups I hope
noahfalk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
326 changes: 326 additions & 0 deletions
326
docs/core/diagnostics/distributed-tracing-collection-walkthroughs.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,326 @@ | ||
| --- | ||
| title: Collect a distributed trace - .NET | ||
| description: A tutorial to collect distributed traces in .NET applications | ||
| ms.topic: tutorial | ||
| ms.date: 03/14/2021 | ||
| --- | ||
|
|
||
| # Collect a distributed trace | ||
|
|
||
| **This article applies to: ✔️** .NET Core 5.0 and later versions **or** any .NET application using the | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| [DiagnosticSource NuGet package](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/5.0.1) version 5 or later | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| .NET applications can be instrumented using the <xref:System.Diagnostics.Activity?displayProperty=nameWithType> API to produce | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| distributed tracing telemetry. In this tutorial you will record this instrumented telemetry with different telemetry collection | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| libraries so that it is available to diagnose application issues. See | ||
| [the instrumentation tutorial](distributed-tracing-instrumentation-walkthroughs.md) if you need to add new instrumentation. | ||
|
|
||
| ## Collect using OpenTelemetry | ||
|
|
||
| ### Prerequisites | ||
|
|
||
| - [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Create an example application | ||
|
|
||
| First you will create an example application that has some distributed trace instrumentation but nothing is being collected. | ||
|
|
||
| ```dotnetcli | ||
| dotnet new console | ||
| ``` | ||
|
|
||
| Applications that target .NET 5 and later already have the necessary distributed tracing APIs included. For apps targeting older | ||
| .NET versions add the [System.Diagnostics.DiagnosticSource NuGet package](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/) | ||
| version 5.0.1 or greater. | ||
| ```dotnetcli | ||
| dotnet add package System.Diagnostics.DiagnosticSource --version 5.0.1 | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| Replace the contents of the generated Program.cs with this example source: | ||
| ```C# | ||
| using System; | ||
| using System.Diagnostics; | ||
| using System.Net.Http; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Sample.DistributedTracing | ||
noahfalk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| class Program | ||
| { | ||
| static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing"); | ||
|
|
||
| static async Task Main(string[] args) | ||
| { | ||
| await DoSomeWork(); | ||
| Console.WriteLine("Example work done"); | ||
| } | ||
|
|
||
| static async Task DoSomeWork() | ||
| { | ||
| using (Activity a = s_source.StartActivity("SomeWork")) | ||
| { | ||
| await StepOne(); | ||
| await StepTwo(); | ||
| } | ||
| } | ||
|
|
||
| static async Task StepOne() | ||
| { | ||
| using (Activity a = s_source.StartActivity("StepOne")) | ||
noahfalk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| await Task.Delay(500); | ||
| } | ||
| } | ||
|
|
||
| static async Task StepTwo() | ||
| { | ||
| using (Activity a = s_source.StartActivity("StepTwo")) | ||
| { | ||
| await Task.Delay(1000); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Running the app does not log anything yet | ||
| ```dotnetcli | ||
| > dotnet run | ||
| Example work done | ||
| ``` | ||
|
|
||
| ### Add logging using OpenTelemetry | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Add the [OpenTelemetry](https://www.nuget.org/packages/OpenTelemetry/) and | ||
| [OpenTelemetry.Exporter.Console](https://www.nuget.org/packages/OpenTelemetry.Exporter.Console/) NuGet packages. | ||
|
|
||
| ```dotnetcli | ||
| dotnet add package OpenTelemetry | ||
| dotnet add package OpenTelemetry.Exporter.Console | ||
| ``` | ||
|
|
||
| Update Program.cs with additional using statments: | ||
| ```C# | ||
| using OpenTelemetry; | ||
| using OpenTelemetry.Trace; | ||
| using System; | ||
noahfalk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| using System.Diagnostics; | ||
| using System.Threading.Tasks; | ||
| ``` | ||
|
|
||
| And update Main() to create the OpenTelemetry TracerProvider: | ||
| ```C# | ||
| public static async Task Main() | ||
| { | ||
| using var tracerProvider = Sdk.CreateTracerProviderBuilder() | ||
| .SetSampler(new AlwaysOnSampler()) | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // Add more libraries | ||
| .AddSource("Sample.DistributedTracing") | ||
noahfalk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Add more exporters | ||
| .AddConsoleExporter() | ||
| .Build(); | ||
|
|
||
| await DoSomeWork(); | ||
| Console.WriteLine("Example work done"); | ||
| } | ||
| ``` | ||
|
|
||
| Now the app logs distributed trace information to the console: | ||
| ```dotnetcli | ||
| > dotnet run | ||
| Activity.Id: 00-35c0e68b0dac3c49be08a9d9cab32579-0b7477e11aa20d40-01 | ||
| Activity.ParentId: 00-35c0e68b0dac3c49be08a9d9cab32579-d95f666d24193f40-01 | ||
| Activity.DisplayName: StepOne | ||
| Activity.Kind: Internal | ||
| Activity.StartTime: 2021-03-15T01:58:10.7661575Z | ||
| Activity.Duration: 00:00:00.5013965 | ||
| Resource associated with Activity: | ||
| service.name: unknown_service:temp | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Activity.Id: 00-35c0e68b0dac3c49be08a9d9cab32579-7ba0fc6d480c9841-01 | ||
| Activity.ParentId: 00-35c0e68b0dac3c49be08a9d9cab32579-d95f666d24193f40-01 | ||
| Activity.DisplayName: StepTwo | ||
| Activity.Kind: Internal | ||
| Activity.StartTime: 2021-03-15T01:58:11.2894853Z | ||
| Activity.Duration: 00:00:01.0188689 | ||
| Resource associated with Activity: | ||
| service.name: unknown_service:temp | ||
|
|
||
| Activity.Id: 00-35c0e68b0dac3c49be08a9d9cab32579-d95f666d24193f40-01 | ||
| Activity.DisplayName: SomeWork | ||
| Activity.Kind: Internal | ||
| Activity.StartTime: 2021-03-15T01:58:10.7647839Z | ||
| Activity.Duration: 00:00:01.5450288 | ||
| Resource associated with Activity: | ||
| service.name: unknown_service:temp | ||
|
|
||
| Example work done | ||
| ``` | ||
|
|
||
| The console exporter is helpful for quick examples or local development but in a production deployment | ||
| you will probably want to send logs to a central logging store. OpenTelemetry supports a variety | ||
| of different logging destinations using different | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| [exporters](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#exporter-library). | ||
| See the [OpenTelemetry getting started](https://github.com/open-telemetry/opentelemetry-dotnet#getting-started) | ||
| instructions for more information on configuring OpenTelemetry. | ||
|
|
||
| ## Collect using Application Insights | ||
|
|
||
| Distributed tracing telemetry is automatically captured after configuring the Application Insights SDK | ||
| ([.NET](https://docs.microsoft.com/en-us/azure/azure-monitor/app/asp-net), [.NET Core](https://docs.microsoft.com/en-us/azure/azure-monitor/app/asp-net-core)) | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| or by enabling [code-less instrumentation](https://docs.microsoft.com/en-us/azure/azure-monitor/app/codeless-overview). | ||
|
|
||
| See the [Application Insights distributed tracing documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/app/distributed-tracing) for more | ||
| information. | ||
|
|
||
| > [!NOTE] | ||
| > Currently Application Insights only supports collecting specific well-known Activity instrumentation and will ignore new user added Activities. Application | ||
| > Insights offers [TrackDependency](https://docs.microsoft.com/en-us/azure/azure-monitor/app/api-custom-events-metrics#trackdependency) as a vendor | ||
| > specific API for adding custom distributed tracing information. | ||
|
|
||
|
|
||
| ## Collect using a custom logging implementation | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Prerequisites | ||
|
|
||
| - [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download/dotnet) or a later version | ||
|
|
||
| ### Create an example application | ||
|
|
||
| ```dotnetcli | ||
| dotnet new console | ||
| ``` | ||
|
|
||
| Applications that target .NET 5 and later already have the necessary distributed tracing APIs included. For apps targeting older | ||
| .NET versions add the [System.Diagnostics.DiagnosticSource NuGet package](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/) | ||
| version 5.0.1 or greater. | ||
| ```dotnetcli | ||
| dotnet add package System.Diagnostics.DiagnosticSource --version 5.0.1 | ||
| ``` | ||
|
|
||
| Replace the contents of the generated Program.cs with this example source: | ||
| ```C# | ||
| using System; | ||
| using System.Diagnostics; | ||
| using System.Net.Http; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Sample.DistributedTracing | ||
| { | ||
| class Program | ||
| { | ||
| static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing"); | ||
|
|
||
| static async Task Main(string[] args) | ||
| { | ||
| await DoSomeWork(); | ||
| Console.WriteLine("Example work done"); | ||
| } | ||
|
|
||
| static async Task DoSomeWork() | ||
| { | ||
| using (Activity a = s_source.StartActivity("SomeWork")) | ||
| { | ||
| await StepOne(); | ||
| await StepTwo(); | ||
| } | ||
| } | ||
|
|
||
| static async Task StepOne() | ||
| { | ||
| using (Activity a = s_source.StartActivity("StepOne")) | ||
| { | ||
| await Task.Delay(500); | ||
| } | ||
| } | ||
|
|
||
| static async Task StepTwo() | ||
| { | ||
| using (Activity a = s_source.StartActivity("StepTwo")) | ||
| { | ||
| await Task.Delay(1000); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Running the app does not log anything yet | ||
| ```dotnetcli | ||
| > dotnet run | ||
| Example work done | ||
| ``` | ||
|
|
||
| ### Add code to log the Activities | ||
|
|
||
| Update Main() with this code that logs Activities: | ||
| ```C# | ||
| static async Task Main(string[] args) | ||
| { | ||
| Activity.DefaultIdFormat = ActivityIdFormat.W3C; | ||
| Console.WriteLine(" {0,-15} {1,-60} {2,-15}", "OperationName", "Id", "Duration"); | ||
| ActivitySource.AddActivityListener(new ActivityListener() | ||
| { | ||
| ShouldListenTo = (source) => true, | ||
| Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllDataAndRecorded, | ||
noahfalk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ActivityStarted = activity => Console.WriteLine("Started: {0,-15} {1,-60}", activity.OperationName, activity.Id), | ||
| ActivityStopped = activity => Console.WriteLine("Stopped: {0,-15} {1,-60} {2,-15}", activity.OperationName, activity.Id, activity.Duration) | ||
| }); | ||
|
|
||
| await DoSomeWork(); | ||
| Console.WriteLine("Example work done"); | ||
| } | ||
| ``` | ||
|
|
||
| The output now includes logging: | ||
| ```dotnetcli | ||
| > dotnet run | ||
| OperationName Id Duration | ||
| Started: SomeWork 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-c447fb302059784f-01 | ||
| Started: StepOne 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-a7c77a4e9a02dc4a-01 | ||
| Stopped: StepOne 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-a7c77a4e9a02dc4a-01 00:00:00.5093849 | ||
| Started: StepTwo 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-9210ad536cae9e4e-01 | ||
| Stopped: StepTwo 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-9210ad536cae9e4e-01 00:00:01.0111847 | ||
| Stopped: SomeWork 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-c447fb302059784f-01 00:00:01.5236391 | ||
| Example work done | ||
| ``` | ||
|
|
||
| Setting <xref:System.Diagnostics.Activity.DefaultIdFormat?displayProperty=nameWithType> is optional | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| but helps ensure the sample produces similar output on different .NET runtime versions. .NET 5.0 uses | ||
| the W3C ID format by default but earlier .NET versions default to using | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <xref:System.Diagnostics.ActivityIdFormat.Hierarchical?displayProperty=nameWithType> as a precaution | ||
| to avoid compatibility issues with older distributed tracing systems. See | ||
| [Activity IDs](distributed-tracing-concepts.md#activity-ids) for more details. | ||
|
|
||
| <xref:System.Diagnostics.ActivityListener?displayProperty=nameWithType> is used to receive callbacks | ||
| during the lifetime of an Activity. | ||
| - <xref:System.Diagnostics.ActivityListener.ShouldListenTo?displayProperty=nameWithType> - Each | ||
| Activity is associated with an ActivitySource which acts as a namespace for a set of Activities. | ||
| This callback is invoked once for each ActivitySource in the process. Returning true indicates | ||
| the listener should be notified about Activities associated with this source. | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - <xref:System.Diagnostics.ActivityListener.Sample?displayProperty=nameWithType> - By default | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <xref:System.Diagnostics.ActivitySource.StartActivity?displayProperty=nameWithType> does not | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| create an Activity object unless some ActivityListener indicates it should be sampled. Returning | ||
| <xref:System.Diagnostics.ActivitySamplingResult.AllDataAndRecorded?displayProperty=nameWithType> | ||
| indicates that the Activity should be created, | ||
| <xref:System.Diagnostics.Activity.IsAllDataRequested?displayProperty=nameWithType> should be set | ||
| to true, and <xref:System.Diagnostics.Activity.ActivityTraceFlags?displayProperty=nameWithType> | ||
| will have the <xref:System.Diagnostics.ActivityTraceFlags.Recorded?displayProperty=nameWithType> | ||
| flag set. IsAllDataRequested can be observed by the instrumented code as a hint that a listener | ||
| wants to ensure that auxilliary Activity information such as Tags and Events are populated. | ||
| The Recorded flag is encoded in the W3C ID and is a hint to other processes involved in the | ||
| distributed trace that this trace should be logged. | ||
| - <xref:System.Diagnostics.ActivityListener.ActivityStarted?displayProperty=nameWithType> and | ||
| <xref:System.Diagnostics.ActivityListener.ActivityStopped?displayProperty=nameWithType> are | ||
| called when an Activity is started and stopped respectively. These callbacks provide an | ||
| oportunity to log any relevant information about the Activity. When an Activity has just | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| started much of the data may still be incomplete and it will be filled in before the Activity | ||
| stops. | ||
|
|
||
| Once an ActivityListener has been created and the callbacks are populated, invoking | ||
| <xref:System.Diagnostics.ActivitySource.AddActivityListener?displayProperty=nameWithType> | ||
noahfalk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| initiates invoking the callbacks. Call | ||
| <xref:System.Diagnostics.ActivityListener.Dispose?displayProperty=nameWithType> to | ||
| stop the flow of callbacks. Beware that in multi-threaded code callback notifications in | ||
| progress could be received while Dispose() is running or even very shortly after it has | ||
| returned. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.