Skip to content

Commit

Permalink
Example and docs for .NET span profiles (#3224)
Browse files Browse the repository at this point in the history
* Enable span profiles for the .NET ride share example app

* Add docs for .NET span profiles

* Add missing file

* Bump Pyroscope.OpenTelemetry to 0.2.0

* Update docs to reflect library update

* Apply suggestions from code review

* Apply suggestions from code review

* Unify span profiling doc introduction across languages

---------

Co-authored-by: Kim Nylander <104772500+knylander-grafana@users.noreply.github.com>
(cherry picked from commit 635b42c)
  • Loading branch information
aleks-p authored and grafana-delivery-bot[bot] committed Apr 19, 2024
1 parent b1a6793 commit 4de36c5
Show file tree
Hide file tree
Showing 11 changed files with 220 additions and 47 deletions.
3 changes: 2 additions & 1 deletion docs/sources/configure-client/trace-span-profiles/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ Key benefits and features:
Get started:

- Configure Pyroscope: Begin sending profiling data to unlock the full potential of Span Profiles
- Client-Side Packages: Easily link traces and profiles using available packages for Go, Ruby, and Java
- Client-Side Packages: Easily link traces and profiles using available packages for Go, Java, Ruby and .NET
- Go: [Span profiles with Traces to profiles (Go)]({{< relref "./go-span-profiles" >}})
- Java: [Span profiles with Traces to profiles (Java)]({{< relref "./java-span-profiles" >}})
- Ruby: [Span profiles with Traces to profiles (Ruby)]({{< relref "./ruby-span-profiles" >}})
- .NET: [Span profiles with Traces to profiles (.NET)]({{< relref "./dotnet-span-profiles" >}})
- Grafana Tempo: Visualize and analyze Span Profiles within the Grafana using a Tempo data source.

To learn more, check out our product announcement blog: [Introducing Span Profiles](/blog/2024/02/06/combining-tracing-and-profiling-for-enhanced-observability-introducing-span-profiles/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: Span profiles with Traces to profiles for .NET
menuTitle: Span profiles with Traces to profiles (.NET)
description: Learn about and configure Span profiles with Traces to profiles in Grafana for .NET applications.
weight: 103
---

# Span profiles with Traces to profiles for .NET

Span Profiles represents a major shift in profiling methodology, enabling deeper analysis of both tracing and profiling data.
Traditional continuous profiling provides an application-wide view over fixed intervals.
In contrast, Span Profiles delivers focused, dynamic analysis on specific execution scopes within applications, such as individual requests or specific trace spans.

This shift enables a more granular view of performance, enhancing the utility of profiles by linking them directly with traces for a comprehensive understanding of application behavior. As a result, engineering teams can more efficiently identify and address performance bottlenecks.

To learn more about Span Profiles, refer to [Combining tracing and profiling for enhanced observability: Introducing Span Profiles](/blog/2024/02/06/combining-tracing-and-profiling-for-enhanced-observability-introducing-span-profiles/).

![span-profiles screenshot](https://grafana.com/static/img/docs/tempo/profiles/tempo-profiles-Span-link-profile-data-source.png)

Pyroscope integrates with distributed tracing systems supporting the [**OpenTelemetry**](https://opentelemetry.io/docs/instrumentation/net/getting-started/) standard.
This integration lets you link traces with the profiling data and find resource usage for specific lines of code for your trace spans.

{{< admonition type="note" >}}
* Only CPU profiling is supported at the moment.
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured.
{{< /admonition >}}

To use Span Profiles, you need to:

* [Configure Pyroscope to send profiling data]({{< relref "../../configure-client" >}})
* Configure a client-side package to link traces and profiles: [.NET](https://github.com/grafana/pyroscope-dotnet/tree/main/Pyroscope/Pyroscope.OpenTelemetry)
* [Configure the Tempo data source in Grafana or Grafana Cloud to discover linked traces and profiles](/grafana-cloud/connect-externally-hosted/data-sources/tempo/configure-tempo-data-source/)

## Before you begin

Your applications must be instrumented for profiling and tracing before you can use span profiles.

* Profiling: Your application must be instrumented with Pyroscope's .NET instrumentation library. Refer to the [.NET]({{< relref "../language-sdks/dotnet" >}}) guide for instructions.
* Tracing: Your application must be instrumented with OpenTelemetry traces. Refer to the [OpenTelemetry](https://opentelemetry.io/docs/net/getting-started/) guide for isntructions.

{{< admonition type="note" >}}
Span profiles in .NET are only supported using [OpenTelemetry manual instrumentation](https://opentelemetry.io/docs/languages/net/instrumentation/)
because Pyroscope's .NET profiler and OpenTelemetry's auto instrumentation are based on separate .NET CLR profilers.
{{< /admonition >}}

## Configure the `Pyroscope.OpenTelemetry` package

To start collecting Span Profiles for your .NET application, you need to include [Pyroscope.OpenTelemetry](https://github.com/grafana/pyroscope-dotnet/tree/main/Pyroscope/Pyroscope.OpenTelemetry) in your code.

This package provides a [`SpanProcessor`](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/BaseProcessor.cs) implementation, which connects the two telemetry signals (traces and profiles) together.

```shell
dotnet add package Pyroscope.OpenTelemetry
```

Next, create and register the `PyroscopeSpanProcessor`:
```csharp
builder.Services.AddOpenTelemetry()
.WithTracing(b =>
{
b
.AddAspNetCoreInstrumentation()
.AddConsoleExporter()
.AddOtlpExporter()
.AddProcessor(new Pyroscope.OpenTelemetry.PyroscopeSpanProcessor());
});
```

With the span processor registered, spans created automatically (for example, HTTP handlers) and manually (`ActivitySource.StartActivity()`) have profiling data associated with them.

## View the span profiles in Grafana Tempo

To view the span profiles in Grafana Tempo, you need to have a Grafana instance running and a data source configured to link traces and profiles.

Refer to the [data source configuration documentation](/docs/grafana/datasources/tempo/configure-tempo-data-source) to see how to configure the visualization to link traces with profiles.

## Examples

Check out the [examples](https://github.com/grafana/pyroscope/tree/main/examples/tracing/tempo) directory for a complete demo application of span profiles in multiple languages.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ To learn more about Span Profiles, refer to [Combining tracing and profiling for

![span-profiles screenshot](https://grafana.com/static/img/docs/tempo/profiles/tempo-profiles-Span-link-profile-data-source.png)

Pyroscope can integrate with distributed tracing systems supporting the [**OpenTelemetry**](https://opentelemetry.io/docs/instrumentation/go/getting-started/) standard.
This integration lets you link traces with the profiling data and find resource usage for specific lines of code for your trace spans.

{{% admonition type="note"%}}
* Only CPU profiling is supported.
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured. Go CPU profiler probes stack traces 100 times per second, meaning that spans shorter than 10ms may not be captured.
{{% /admonition %}}

To use Span Profiles, you need to:

* [Configure Pyroscope to send profiling data]({{< relref "../../configure-client" >}})
* Configure a client-side package to link traces and profiles: [Go](https://github.com/grafana/otel-profiling-go)
* [Configure Tempo data source in Grafana or Grafana Cloud to discover linked traces and profiles](/grafana-cloud/connect-externally-hosted/data-sources/tempo/configure-tempo-data-source/)
* [Configure the Tempo data source in Grafana or Grafana Cloud to discover linked traces and profiles](/grafana-cloud/connect-externally-hosted/data-sources/tempo/configure-tempo-data-source/)

## Before you begin

Expand All @@ -33,16 +41,6 @@ Your applications must be instrumented for profiling and tracing before you can
* Profiling: Your application must be instrumented with Pyroscope's Go SDK. If you haven't done this yet, please refer to the [Go (push mode)]({{< relref "../language-sdks/go_push" >}}) guide.
* Tracing: Your application must be instrumented with OpenTelemetry traces. If you haven't done this yet, please refer to the [OpenTelemetry](https://opentelemetry.io/docs/go/getting-started/) guide.

### OpenTelemetry support

Pyroscope can integrate with distributed tracing systems supporting [**OpenTelemetry**](https://opentelemetry.io/docs/instrumentation/go/getting-started/) standard, which allows you to
link traces with the profiling data, and find resource usage for specific lines of code for your trace spans.

{{% admonition type="note"%}}
* Only CPU profiling is supported.
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured. Go CPU profiler probes stack traces 100 times per second, meaning that spans shorter than 10ms may not be captured.
{{% /admonition %}}

## Configure the `otel-profiling-go` package

To start collecting Span Profiles for your Go application, you need to include the [`otel-profiling-go`](https://github.com/pyroscope-io/otel-profiling-go) package in your code.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,41 @@
title: Span profiles with Traces to profiles for Java
menuTitle: Span profiles with Traces to profiles (Java)
description: Learn about and configure Span profiles with Traces to profiles in Grafana for the Java language.
weight: 100
weight: 101
---

# Span profiles with Traces to profiles for Java

![span-profiles screenshot](https://grafana.com/static/img/docs/tempo/profiles/tempo-profiles-Span-link-profile-data-source.png)

## Before you begin
Span Profiles represents a major shift in profiling methodology, enabling deeper analysis of both tracing and profiling data.
Traditional continuous profiling provides an application-wide view over fixed intervals.
In contrast, Span Profiles delivers focused, dynamic analysis on specific execution scopes within applications, such as individual requests or specific trace spans.

Your applications must be instrumented for profiling and tracing before you can use span profiles.
This shift enables a more granular view of performance, enhancing the utility of profiles by linking them directly with traces for a comprehensive understanding of application behavior. As a result, engineering teams can more efficiently identify and address performance bottlenecks.

* Profiling: Your application must be instrumented with Pyroscope's Java client SDK. If you haven't done this yet, please refer to the [Java ()]({{< relref "../language-sdks/java" >}}) guide.
* Tracing: Your application must be instrumented with OpenTelemetry traces. If you haven't done this yet, please refer to the [OpenTelemetry](https://opentelemetry.io/docs/java/getting-started/) guide.
To learn more about Span Profiles, refer to [Combining tracing and profiling for enhanced observability: Introducing Span Profiles](/blog/2024/02/06/combining-tracing-and-profiling-for-enhanced-observability-introducing-span-profiles/).

## OpenTelemetry support
![span-profiles screenshot](https://grafana.com/static/img/docs/tempo/profiles/tempo-profiles-Span-link-profile-data-source.png)

Pyroscope can integrate with distributed tracing systems supporting [**OpenTelemetry**](https://opentelemetry.io/docs/instrumentation/java/getting-started/) standard which allows you to
link traces with the profiling data, and find resource usage for specific lines of code for your trace spans
Pyroscope integrates with distributed tracing systems supporting the [**OpenTelemetry**](https://opentelemetry.io/docs/instrumentation/java/getting-started/) standard.
This integration lets you link traces with the profiling data and find resource usage for specific lines of code for your trace spans.

{{< admonition type="note" >}}
* Only CPU profiling is supported at the moment.
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured. Java CPU profiler probes stack traces 100 times per second, meaning that spans shorter than 10ms may not be captured.
* Only CPU profiling is supported at the moment.
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured.
{{< /admonition >}}

To use Span Profiles, you need to:

* [Configure Pyroscope to send profiling data]({{< relref "../../configure-client" >}})
* Configure a client-side package to link traces and profiles: [Java](https://github.com/grafana/otel-profiling-java)
* [Configure the Tempo data source in Grafana or Grafana Cloud to discover linked traces and profiles](/grafana-cloud/connect-externally-hosted/data-sources/tempo/configure-tempo-data-source/)

## Before you begin

Your applications must be instrumented for profiling and tracing before you can use span profiles.

* Profiling: Your application must be instrumented with Pyroscope's Java client SDK. Refer to the [Java]({{< relref "../language-sdks/java" >}}) guide for instructions.
* Tracing: Your application must be instrumented with OpenTelemetry traces. Refer to the [OpenTelemetry](https://opentelemetry.io/docs/java/getting-started/) guide for instructions.

## Configure the otel-profiling-java package

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,41 @@
title: Span profiles with Traces to profiles for Ruby
menuTitle: Span profiles with Traces to profiles (Ruby)
description: Learn about and configure Span profiles with Traces to profiles in Grafana for the Ruby language.
weight: 100
weight: 102
---

# Span profiles with Traces to profiles for Ruby

![span-profiles screenshot](https://grafana.com/static/img/docs/tempo/profiles/tempo-profiles-Span-link-profile-data-source.png)

## Before you begin
Span Profiles represents a major shift in profiling methodology, enabling deeper analysis of both tracing and profiling data.
Traditional continuous profiling provides an application-wide view over fixed intervals.
In contrast, Span Profiles delivers focused, dynamic analysis on specific execution scopes within applications, such as individual requests or specific trace spans.

Your applications must be instrumented for profiling and tracing before you can use span profiles.
This shift enables a more granular view of performance, enhancing the utility of profiles by linking them directly with traces for a comprehensive understanding of application behavior. As a result, engineering teams can more efficiently identify and address performance bottlenecks.

* Profiling: Your application must be instrumented with Pyroscope's Ruby SDK. If you haven't done this yet, please refer to the [Ruby (push mode)]({{< relref "../language-sdks/ruby" >}}) guide.
* Tracing: Your application must be instrumented with OpenTelemetry traces. If you haven't done this yet, please refer to the [OpenTelemetry](https://opentelemetry.io/docs/ruby/getting-started/) guide.
To learn more about Span Profiles, refer to [Combining tracing and profiling for enhanced observability: Introducing Span Profiles](/blog/2024/02/06/combining-tracing-and-profiling-for-enhanced-observability-introducing-span-profiles/).

## OpenTelemetry support
![span-profiles screenshot](https://grafana.com/static/img/docs/tempo/profiles/tempo-profiles-Span-link-profile-data-source.png)

Pyroscope can integrate with distributed tracing systems supporting [**OpenTelemetry**](https://opentelemetry.io/docs/instrumentation/ruby/getting-started/) standard which allows you to
link traces with the profiling data, and find resource usage for specific lines of code for your trace spans
Pyroscope integrates with distributed tracing systems supporting the [**OpenTelemetry**](https://opentelemetry.io/docs/instrumentation/ruby/getting-started/) standard.
This integration lets you link traces with the profiling data and find resource usage for specific lines of code for your trace spans.

{{< admonition type="note" >}}
* Only CPU profiling is supported at the moment.
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured. Ruby CPU profiler probes stack traces 100 times per second, meaning that spans shorter than 10ms may not be captured.
* Only CPU profiling is supported at the moment.
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured.
{{< /admonition >}}

To use Span Profiles, you need to:

* [Configure Pyroscope to send profiling data]({{< relref "../../configure-client" >}})
* Configure a client-side package to link traces and profiles: [Ruby](https://github.com/grafana/otel-profiling-ruby)
* [Configure the Tempo data source in Grafana or Grafana Cloud to discover linked traces and profiles](/grafana-cloud/connect-externally-hosted/data-sources/tempo/configure-tempo-data-source/)

## Before you begin

Your applications must be instrumented for profiling and tracing before you can use span profiles.

* Profiling: Your application must be instrumented with Pyroscope's Ruby SDK. Refer to the [Ruby]({{< relref "../language-sdks/ruby" >}}) guide for instructions.
* Tracing: Your application must be instrumented with OpenTelemetry traces. Refer to the [OpenTelemetry](https://opentelemetry.io/docs/ruby/getting-started/) guide for instructions.

## Configure the otel-profiling-ruby package

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,9 @@ services:
build:
context: .
dockerfile: Dockerfile.load-generator

depends_on:
- pyroscope
- us-east
- eu-north
- ap-south
- ap-south-alpine
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Pyroscope" Version="0.8.0" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.8.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.8.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.8.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.8.1" />
<PackageReference Include="Pyroscope.OpenTelemetry" Version="0.2.0" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Collections;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace Example;
using OpenTelemetry.Trace;

using System.Collections;
using Microsoft.AspNetCore.Builder;
using Pyroscope.OpenTelemetry;

namespace Example;

public static class Program
{
private static readonly List<FileStream> Files = new();
public const string CustomActivitySourceName = "Example.ScooterService";
public static void Main(string[] args)
{
for (int i = 0; i < 1024; i++)
Expand All @@ -20,12 +26,25 @@ public static void Main(string[] args)
}
object globalLock = new();
var strings = new List<string>();

var orderService = new OrderService();
var bikeService = new BikeService(orderService);
var scooterService = new ScooterService(orderService);
var carService = new CarService(orderService);

var app = WebApplication.CreateBuilder(args).Build();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
.WithTracing(b =>
{
b
.AddAspNetCoreInstrumentation()
.AddSource(CustomActivitySourceName)
.AddConsoleExporter()
.AddOtlpExporter()
.AddProcessor(new PyroscopeSpanProcessor());
});
var app = builder.Build();

app.MapGet("/bike", () =>
{
bikeService.Order(1);
Expand Down Expand Up @@ -99,7 +118,7 @@ public static void Main(string[] args)
{
throw new Exception("foobar" + i);
}
catch (Exception e)
catch (Exception)
{
}
}
Expand All @@ -125,4 +144,4 @@ public static void Main(string[] args)

app.Run();
}
}
}
Loading

0 comments on commit 4de36c5

Please sign in to comment.