Skip to content

Commit a3c886e

Browse files
authored
Add helper packages that enable span profiles (#58)
* Add package for span profiles using OpenTracing * Add package for span profiles using OpenTelemetry * Improve README files * Add GitHub workflows for building and releasing the tracing helper packages * Add support to tag root and nested spans for OTEL * Add support to tag root and nested spans for OpenTracing * Update readme for OpenTracing
1 parent 493a251 commit a3c886e

File tree

12 files changed

+576
-0
lines changed

12 files changed

+576
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Build tracing libraries
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build-tracing-lib-opentracing:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v2
15+
with:
16+
submodules: 'true'
17+
- uses: actions/setup-dotnet@v3
18+
with:
19+
dotnet-version: '6.0'
20+
- run: dotnet build -c Release
21+
working-directory: Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTracing
22+
build-tracing-lib-opentelemetry:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v2
27+
with:
28+
submodules: 'true'
29+
- uses: actions/setup-dotnet@v3
30+
with:
31+
dotnet-version: '6.0'
32+
- run: dotnet build -c Release
33+
working-directory: Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTelemetry
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Release managed helper
2+
3+
on:
4+
push:
5+
tags:
6+
- v*-pyroscope
7+
8+
jobs:
9+
release-tracing-lib-opentracing:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v2
14+
with:
15+
submodules: 'true'
16+
- uses: actions/setup-dotnet@v3
17+
with:
18+
dotnet-version: '6.0'
19+
- run: dotnet build -c Release
20+
working-directory: Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTracing
21+
- name: Publish the package to nuget.org
22+
run: dotnet nuget push bin/Release/*.nupkg -k $NUGET_AUTH_TOKEN -s https://api.nuget.org/v3/index.json
23+
working-directory: Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTracing
24+
env:
25+
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }}
26+
- name: Release
27+
uses: softprops/action-gh-release@v1
28+
if: startsWith(github.ref, 'refs/tags/')
29+
with:
30+
files: |
31+
./Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTracing/bin/Release/net6.0/Pyroscope.Tracing.OpenTracing.dll
32+
./Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTracing/bin/Release/Pyroscope.Tracing.OpenTracing*.nupkg
33+
release-tracing-lib-opentelemetry:
34+
runs-on: ubuntu-latest
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@v2
38+
with:
39+
submodules: 'true'
40+
- uses: actions/setup-dotnet@v3
41+
with:
42+
dotnet-version: '6.0'
43+
- run: dotnet build -c Release
44+
working-directory: Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTelemetry
45+
- name: Publish the package to nuget.org
46+
run: dotnet nuget push bin/Release/*.nupkg -k $NUGET_AUTH_TOKEN -s https://api.nuget.org/v3/index.json
47+
working-directory: Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTelemetry
48+
env:
49+
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }}
50+
- name: Release
51+
uses: softprops/action-gh-release@v1
52+
if: startsWith(github.ref, 'refs/tags/')
53+
with:
54+
files: |
55+
./Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTelemetry/bin/Release/net6.0/Pyroscope.Tracing.OpenTelemetry.dll
56+
./Pyroscope/Pyroscope.Tracing/Pyroscope.Tracing.OpenTelemetry/bin/Release/Pyroscope.Tracing.OpenTelemetry*.nupkg
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
8+
<PackageVersion>0.1.0</PackageVersion>
9+
<AssemblyVersion>0.1.0</AssemblyVersion>
10+
<FileVersion>0.1.0</FileVersion>
11+
<LangVersion>10</LangVersion>
12+
<PackageReadmeFile>README.md</PackageReadmeFile>
13+
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="OpenTelemetry" Version="1.8.0" />
17+
<PackageReference Include="Pyroscope" Version="0.8.14" />
18+
<None Include="README.md" Pack="true" PackagePath="\"/>
19+
</ItemGroup>
20+
21+
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.5.002.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pyroscope.Tracing.OpenTelemetry", "Pyroscope.Tracing.OpenTelemetry.csproj", "{42160563-B7D4-41D6-89DE-9CEDEEB542AA}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{42160563-B7D4-41D6-89DE-9CEDEEB542AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{42160563-B7D4-41D6-89DE-9CEDEEB542AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{42160563-B7D4-41D6-89DE-9CEDEEB542AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{42160563-B7D4-41D6-89DE-9CEDEEB542AA}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {F472AA5F-5941-4FC4-B363-820E27A5A505}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using System.Diagnostics;
2+
using OpenTelemetry;
3+
4+
namespace Pyroscope.Tracing.OpenTelemetry;
5+
6+
public class PyroscopeSpanProcessor : BaseProcessor<Activity>
7+
{
8+
private const string ProfileIdSpanTagKey = "pyroscope.profile.id";
9+
private readonly Config _config;
10+
11+
private PyroscopeSpanProcessor()
12+
{
13+
_config = new Config();
14+
}
15+
16+
public override void OnStart(Activity data)
17+
{
18+
if (_config.RootSpanOnly && !IsRootSpan(data))
19+
{
20+
return;
21+
}
22+
23+
try
24+
{
25+
var spanId = data.SpanId.ToString();
26+
var spanIdLong = Convert.ToUInt64(spanId.ToUpper(), 16);
27+
28+
// Establish a two-way connection between the span and profiling data
29+
Profiler.Instance.SetProfileId(spanIdLong);
30+
data.AddTag(ProfileIdSpanTagKey, spanId);
31+
}
32+
catch (Exception ex)
33+
{
34+
Console.WriteLine($"Caught exception while setting profile id in profiler instance: {ex.Message}");
35+
}
36+
}
37+
38+
public override void OnEnd(Activity data)
39+
{
40+
if (IsRootSpan(data))
41+
{
42+
Profiler.Instance.SetProfileId(0); // TODO: Replace with ResetContext()
43+
return;
44+
}
45+
if (_config.RootSpanOnly)
46+
{
47+
return;
48+
}
49+
50+
try
51+
{
52+
var parentSpanId = data.ParentSpanId.ToString();
53+
var spanIdLong = Convert.ToUInt64(parentSpanId.ToUpper(), 16);
54+
Profiler.Instance.SetProfileId(spanIdLong);
55+
}
56+
catch (Exception ex)
57+
{
58+
Console.WriteLine($"Caught exception while restoring previous profile id in profiler instance: {ex.Message}");
59+
}
60+
}
61+
62+
private static bool IsRootSpan(Activity data)
63+
{
64+
var parent = data.Parent;
65+
return parent == null || parent.HasRemoteParent;
66+
}
67+
68+
internal class Config
69+
{
70+
public bool RootSpanOnly { get; set; } = true;
71+
}
72+
73+
public class Builder
74+
{
75+
private PyroscopeSpanProcessor _processor = new PyroscopeSpanProcessor();
76+
77+
public Builder WithRootSpanOnly(bool RootSpanOnly)
78+
{
79+
_processor._config.RootSpanOnly = RootSpanOnly;
80+
return this;
81+
}
82+
83+
public PyroscopeSpanProcessor Build()
84+
{
85+
return _processor;
86+
}
87+
}
88+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## Span profiles for OpenTelemetry
2+
3+
This package enables applications that already rely on [OpenTelemetry](https://opentelemetry.io/docs/instrumentation/net/getting-started/) for distributed tracing and Pyroscope for continuous profiling to link the tracing and profiling data together.
4+
5+
See https://grafana.com/docs/pyroscope/latest/configure-client/trace-span-profiles/ for more information.
6+
7+
### Prerequisites
8+
- Your .NET application is instrumented with [Pyroscope's profiler](https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/dotnet/)
9+
- Your .NET application is instrumented (manually) with [OpenTelemetry](https://opentelemetry.io/docs/instrumentation/net/getting-started/)
10+
11+
### Integration
12+
13+
Add the following package to your project:
14+
15+
```shell
16+
dotnet add package Pyroscope.Tracing.OpenTelemetry
17+
```
18+
19+
Register the `PyroscopeSpanProcessor` in your OpenTelemetry integration:
20+
21+
```csharp
22+
23+
builder.Services.AddOpenTelemetry()
24+
.WithTracing(b =>
25+
{
26+
b
27+
.AddAspNetCoreInstrumentation()
28+
.AddConsoleExporter()
29+
.AddOtlpExporter()
30+
.AddProcessor(new PyroscopeSpanProcessor.Builder()
31+
.WithRootSpanOnly(true)
32+
.Build());
33+
});
34+
35+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
8+
<PackageVersion>0.1.0</PackageVersion>
9+
<AssemblyVersion>0.1.0</AssemblyVersion>
10+
<FileVersion>0.1.0</FileVersion>
11+
<LangVersion>10</LangVersion>
12+
<PackageReadmeFile>README.md</PackageReadmeFile>
13+
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="OpenTracing" Version="0.12.1" />
17+
<PackageReference Include="Pyroscope" Version="0.8.14" />
18+
<None Include="README.md" Pack="true" PackagePath="\"/>
19+
</ItemGroup>
20+
21+
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.5.002.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pyroscope.Tracing.OpenTracing", "Pyroscope.Tracing.OpenTracing.csproj", "{311866C4-042D-4F43-B025-CC142FDD02B3}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{311866C4-042D-4F43-B025-CC142FDD02B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{311866C4-042D-4F43-B025-CC142FDD02B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{311866C4-042D-4F43-B025-CC142FDD02B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{311866C4-042D-4F43-B025-CC142FDD02B3}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {BFF488AB-A4B8-4DC3-91FE-02E755751CB8}
24+
EndGlobalSection
25+
EndGlobal

0 commit comments

Comments
 (0)